西安集训第二天---状压dp
2017-08-07 17:36
190 查看
热身题:
https://nanti.jisuanke.com/t/16447
挺有意思的一道题,标准的dp
我的思路+代码:
dp[i][j][k][r] 走到i,j 这个点,已经用过几个技能了,并且当前能力值还剩下几步。的最小伤害
r=0 表示当前没有buff。
dp[505][505][15][10]; // 500*500*10*5 =12500000
下面我们考虑一下 转移方程:
对于i,j
dp[i][j][k][r] = ( dp[i-1][j][k][r+1] dp[i][j-1][k][r+1] ) 但是我们无法知道攻击力是多少,所以无法转移,
但是如果我们吧增加的攻击力放入其中,那么需要100*250000显然太大了
正解:
因为我们只需要终点的状态
且为了最优解肯定是技能结束的状态,所以我们不需要讨论开技能时候的转移,我们只需要开完技能之后的状态转移即可。
我们考虑 dp[i][j][k] 表示到ij这个点 用了k次技能,如果这个点 不使用技能那么转移
如果使用技能我们直接dfs 更新这一次决策可能结束的位置,以及对应位置的伤害,然后更新相对应位置的dp值。 因为每次只能走五步,所以这个dfs的复杂度并不高
总的时间复杂度= 500*500*10*6??? 好像最多只会更新6个位置
有一个细节:
假设在某个点开始一个技能
那么dfs中的伤害s 代表的是已经走到i,j的伤害值,所以这个点的伤害必然是不需要计算了的
同时这个点的攻击力也是不能加的
https://nanti.jisuanke.com/t/16447
挺有意思的一道题,标准的dp
我的思路+代码:
dp[i][j][k][r] 走到i,j 这个点,已经用过几个技能了,并且当前能力值还剩下几步。的最小伤害
r=0 表示当前没有buff。
dp[505][505][15][10]; // 500*500*10*5 =12500000
下面我们考虑一下 转移方程:
对于i,j
dp[i][j][k][r] = ( dp[i-1][j][k][r+1] dp[i][j-1][k][r+1] ) 但是我们无法知道攻击力是多少,所以无法转移,
但是如果我们吧增加的攻击力放入其中,那么需要100*250000显然太大了
正解:
因为我们只需要终点的状态
且为了最优解肯定是技能结束的状态,所以我们不需要讨论开技能时候的转移,我们只需要开完技能之后的状态转移即可。
我们考虑 dp[i][j][k] 表示到ij这个点 用了k次技能,如果这个点 不使用技能那么转移
如果使用技能我们直接dfs 更新这一次决策可能结束的位置,以及对应位置的伤害,然后更新相对应位置的dp值。 因为每次只能走五步,所以这个dfs的复杂度并不高
总的时间复杂度= 500*500*10*6??? 好像最多只会更新6个位置
有一个细节:
假设在某个点开始一个技能
那么dfs中的伤害s 代表的是已经走到i,j的伤害值,所以这个点的伤害必然是不需要计算了的
同时这个点的攻击力也是不能加的
#include <bits/stdc++.h> using namespace std; int dp[505][505][15]; int a[505][505]; int n,m,t,kk,atk,h; int count(int x,int y){ // 计算伤害 敌方攻击,我方攻击 int num=(h-1)/y; return x*num; } void dfs(int K,int i,int j,int ATK,int rest,int s){ // 这是第几次发动技能,i,j点,当前的攻击力,还能走几步,累计的伤害值 if(rest<kk){ s+=count(a[i][j],ATK+a[i][j] ); // 第一个点的伤害是不能计算的 ATK+=a[i][j]; } if(rest==0){ // 这一步是最后一步 dp[i][j][K]=min(dp[i][j][K], s); // printf("end:%d %d %d atk=%d shanghai =%d %d\n",i,j, K,ATK+a[i][j], count(a[i][j],ATK+a[i][j]) ,dp[i][j][K]); return; } if(i<n) // -> dfs(K,i+1,j,ATK,rest-1,s ); if(j<m) dfs(K,i,j+1,ATK,rest-1,s ); } int main(){ freopen("1.txt","r",stdin); scanf("%d %d %d %d %d %d",&n,&m,&t,&kk,&h,&atk); for(int k=0;k<=t;k++) for(int i=0;i<=n;i++) for(int j=0;j<=m;j++) dp[i][j][k]=1<<30; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&a[i][j]); for(int i=0;i<=t;i++) dp[1][1][i]=0; for(int k=0;k<=t;k++) for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ // 首先考虑在这个点不用技能,向右或者下走 if(i+1<=n) dp[i+1][j][k] = min( dp[i+1][j][k], dp[i][j][k]+count(a[i+1][j],atk) ); if(j+1<=m) dp[i][j+1][k] = min(dp[i][j+1][k] , dp[i][j][k]+count(a[i][j+1],atk)); if(k<t){ // 能够用技能 ,已经用了k次 // printf("dfs: %d %d k=%d s=%d \n\n",i,j,k+1,dp[i][j][k]); dfs(k+1,i,j,atk,kk,dp[i][j][k]); } } printf("%d\n",dp [m][t]); }
相关文章推荐
- [2018雅礼集训1-23]盛大的庆典 状压DP
- UOJ#37.【清华集训2014】主旋律 状压DP
- 【NOI集训】【XJ】状压dp
- 【XSY1285】【BZOJ3814】【清华集训2014】简单回路 状压DP
- 集训-一笔画(状压DP)
- POJ1185:炮兵阵地(状压dp)
- POJ 1185 炮兵阵地(状压DP)
- BZOJ3295:[Zjoi2015]地震后的幻想乡(状压dp)
- Light oj 1147 - Tug of War(状压dp)
- (状压dp)uva 10817 Headmaster's Headache
- Bzoj 1087: [SCOI2005]互不侵犯King(状压DP)
- ZOJ3471Most Powerful 状压DP
- 【codevs 2451】互不侵犯king 状压dp
- 西安集训第六天-----一般的数据结构知识
- NOIP2016愤怒的小鸟(状压Dp)
- POJ 2288 Islands and Bridges (状压DP)
- NOI 2001 炮兵阵地 状压dp
- poj 3254 状压dp
- HDU 1074 Doing Homework(状压DP)
- bzoj 1097 [POI2007]旅游景点atr(最短路,状压DP)