蒜头君有一只坐骑,人马。

一天,蒜头君骑着他的坐骑走上了一片 n×m 的大荒野,一开始时,蒜头君在 (1,1) 点,他要前往 (n,m) 点,蒜头君的人马每次可以向右或向下移动一格。然而这片荒野并不平静,除了起点和终点外每个点都有一只怪物会袭击蒜头君。

然而蒜头君的人马强大无比,它会先对怪物造成等同于它攻击力的伤害,然后蒜头君才会受到怪物的攻击,伤害等同于怪物的攻击力。然后人马再攻击怪物,怪物再攻击蒜头君,直至怪物死去,假设每个怪物具有相同的体力。

此外,蒜头君的人马还有一个强大无比的技能,使用该技能会使蒜头君接下来 k 次移动,每一次移动后增加等同于移动到的格子的怪物的攻击力,kk 次移动后,人马攻击力恢复至初始攻击力。人马必须在当前一个技能释放完后才可以释放下一个技能,且一共可释放技能的次数有限,那么试问蒜头君从起点到终点最少受到多少点伤害。

注意:蒜头君的体力是无限的。

输入格式

第一行六个正整数 n,m,t,k,h,atkn,m,t,k,h,atk,表示地图长度、宽度、人马技能可使用次数、人马技能持续移动次数、每只怪物的体力和人马的初始攻击力。

接下来 nn 行,每行 mm 个整数,表示每个点的怪物的攻击力。保证 (1,1)点、(n,m)点为 0,其他点为正整数。

输出格式

输出一个整数,表示蒜头君受到的最小伤害。




样例输入

4 3 2 1 7 4
0 2 4
3 5 1
2 3 2
5 4 0



样例输出

3
题解:dp+dfs
首先,定义f[i][j][l]为在(i,j)时有l次技能的最小值,因为技能不能打断,使用后自动触发,所以无后效性显然,对于x,y转移有两种情况,一种直接移动,一种是用技能直接移动不说了,用技能则调用一次dfs,转移到k次以后的节点





1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 using namespace std;
6 int f[501][501][11],h,atk,n,m,k,a[501][501],t,ans;
7 int cal(int x,int y,int A)
8 {
9 return (h-1)/A*a[x][y];
10 }
11 void dfs(int x,int y,int p,int z,int s,int A)
12 {
13 if (p>k||(x==n&&y==m))
14 {
15 f[x][y][z-1]=min(s,f[x][y][z-1]);
16 return;
17 }
18 if (x+1<=n) dfs(x+1,y,p+1,z,s+cal(x+1,y,A+a[x+1][y]),A+a[x+1][y]);
19 if (y+1<=m) dfs(x,y+1,p+1,z,s+cal(x,y+1,A+a[x][y+1]),A+a[x][y+1]);
20 }
21 int main()
22 {int i,j,l;
23 cin>>n>>m>>t>>k>>h>>atk;
24 for (i=1;i<=n;i++)
25 {
26 for (j=1;j<=m;j++)
27 {
28 scanf("%d",&a[i][j]);
29 }
30 }
31 memset(f,127/3,sizeof(f));
32 f[1][1][t]=0;
33 for (i=1;i<=n;i++)
34 {
35 for (j=1;j<=m;j++)
36 {
37 for (l=t;l>=0;l--)
38 {
39 if (l)
40 dfs(i,j,1,l,f[i][j][l],atk);
41 if (i+1<=n)
42 f[i+1][j][l]=min(f[i+1][j][l],f[i][j][l]+cal(i+1,j,atk));
43 if (j+1<=m)
44 f[i][j+1][l]=min(f[i][j+1][l],f[i][j][l]+cal(i,j+1,atk));
45 }
46 }
47 }
48 ans=2e9;
49 for (i=0;i<=t;i++)
50 ans=min(ans,f[n][m][i]);
51 cout<<ans;
52 }