计蒜客模拟赛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 }

 

posted @ 2017-07-31 18:39  Leohh  阅读(294)  评论(0编辑  收藏  举报