计蒜客模拟赛D1T3 蒜头君的坐骑:用dfs转移dp
题目链接:https://nanti.jisuanke.com/t/16447
题意:
蒜头君有一只坐骑,人马。
一天,蒜头君骑着他的坐骑走上了一片n*m的大荒野,一开始时,蒜头君在(1,1)点,他要前往(n,m)点,蒜头君的人马每次可以向右或向下移动一格。然而这片荒野并不平静,除了起点和终点外每个点都有一只怪物会袭击蒜头君。
然而蒜头君的人马强大无比,它会先对怪物造成等同于它攻击力的伤害,然后蒜头君才会受到怪物的攻击,伤害等同于怪物的攻击力。然后人马再攻击怪物,怪物再攻击蒜头君,直至怪物死去,假设每个怪物具有相同的体力。
此外,蒜头君的人马还有一个强大无比的技能,使用该技能会使蒜头君接下来 k次移动,每一次移动后增加等同于移动到的格子的怪物的攻击力,k次移动后,人马攻击力恢复至初始攻击力。人马必须在当前一个技能释放完后才可以释放下一个技能,且一共可释放技能的次数有限,那么试问蒜头君从起点到终点最少受到多少点伤害。
注意:蒜头君的体力是无限的。
题解:
用dp[i][j][p]表示在(i , j)点已经用完了p次技能时的最小伤害。
用us[i][j][p]表示在(i , j)点已经正在用第p次技能时的最小伤害。
那么到终点的最小伤害值 = min( min{dp[n][m][p]} , min{us[n][m][p]} ) (枚举p:0 <= p <= t)
接下来考虑如何转移。
现在在(i , j)点,要么不用技能,要么用技能。
① 如果不用技能,那就直接转移:
dp[i+1][j] = min(dp[i+1][j] , dp[i][j] + 在(i+1 , j)点受到的伤害值)
dp[i][j+1] = min(dp[i][j+1] , dp[i][j] + 在(i , j+1)点受到的伤害值)
② 如果用技能,那么用dfs转移到每一个可能的用完这次技能的终点,同时在dfs中更新us数组的值。
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #define MAX_N 505 5 #define MAX_T 15 6 #define INF 10000000 7 8 using namespace std; 9 10 int n,m,t,k,h,atk; 11 int a[MAX_N][MAX_N]; 12 int dp[MAX_N][MAX_N][MAX_T]; 13 int us[MAX_N][MAX_N][MAX_T]; 14 15 void read() 16 { 17 cin>>n>>m>>t>>k>>h>>atk; 18 for(int i=1;i<=n;i++) 19 { 20 for(int j=1;j<=m;j++) 21 { 22 cin>>a[i][j]; 23 } 24 } 25 } 26 27 void init() 28 { 29 for(int i=1;i<=n;i++) 30 { 31 for(int j=1;j<=m;j++) 32 { 33 for(int k=0;k<=t;k++) 34 { 35 dp[i][j][k]=INF; 36 us[i][j][k]=INF; 37 } 38 } 39 } 40 } 41 42 void dfs(int x,int y,int tot,int step,int atk,int dam) 43 { 44 us[x][y][tot]=min(us[x][y][tot],dam); 45 if(step==k) 46 { 47 dp[x][y][tot]=min(dp[x][y][tot],dam); 48 return; 49 } 50 dfs(x+1,y,tot,step+1,atk+a[x+1][y],dam+((h-1)/(atk+a[x+1][y])*a[x+1][y])); 51 dfs(x,y+1,tot,step+1,atk+a[x][y+1],dam+((h-1)/(atk+a[x][y+1])*a[x][y+1])); 52 } 53 54 void solve() 55 { 56 init(); 57 dp[1][1][0]=0; 58 for(int i=1;i<=n;i++) 59 { 60 for(int j=1;j<=m;j++) 61 { 62 for(int p=0;p<=t;p++) 63 { 64 if(dp[i][j][p]>=INF) continue; 65 if(i+1<=n) dp[i+1][j][p]=min(dp[i+1][j][p],dp[i][j][p]+((h-1)/atk)*a[i+1][j]); 66 if(j+1<=m) dp[i][j+1][p]=min(dp[i][j+1][p],dp[i][j][p]+((h-1)/atk)*a[i][j+1]); 67 if(p<t) dfs(i,j,p+1,0,atk,dp[i][j][p]); 68 } 69 } 70 } 71 } 72 73 void print() 74 { 75 int minn=INF; 76 for(int i=0;i<=t;i++) 77 { 78 minn=min(minn,dp[n][m][i]); 79 minn=min(minn,us[n][m][i]); 80 } 81 cout<<minn<<endl; 82 } 83 84 int main() 85 { 86 read(); 87 solve(); 88 print(); 89 }