题目:
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define NIL 1e9
int a[1005][1005],dp[1005][1005],dir[4][2] = {{1,1},{-1,1},{-1,-1},{1,-1}};
int main()
{
int n,m,x,y,v,c,ans;
cin >> n >> m >> x >> y >> v >> c;
for(int i = 1;i <= n;i++)
for(int j = 1;j <= m;j++)
cin >> a[i][j];
for(int k = 0;k < 4;k++){
for(int i = x;i > 0 && i <= n;i -= dir[k][0]){
for(int j = y;j > 0 && j <= m;j -= dir[k][1]){
if(i == x && j == y) dp[i][j] = v; //在出发地血量为v
else if(i == x) dp[i][j] = min(c,dp[i][j + dir[k][1]] + a[i][j]);//到达出发地这一行要考虑前一步从哪里来的
else if(j == y) dp[i][j] = min(c,dp[i + dir[k][0]][j] + a[i][j]);
else dp[i][j] = min(c,max(dp[i][j + dir[k][1]] + a[i][j],dp[i + dir[k][0]][j] + a[i][j]));
if(dp[i][j] <= 0) dp[i][j] = -NIL;//说明这人在此处挂了
}
}
}
ans = max(max(dp[1][1],dp[1][m]),max(dp[n][1],dp[n][m]));//将这个人到达四个出口时的血量中选取最大值
if(ans < 0) cout << "-1" << endl;
else cout << ans << endl;
return 0;
}
这是一道dp题,dp[i][j]代表在i,j位置的血量。那么我们从起点可以往四个不同的方向走,每走到一个新的位置,你要考虑你是从哪个位置过来的。如果走到与起点的横坐标相同的位置,那么前一步要么是从左边来的,要么是从右边来的,不可能是从上下边来的。如果走到与起点纵坐标相同的地方,要么是从上边来的,要么是从下边来的,不可能是从左右边过来的。排除这两种特殊情况,其余位置的前一步要考虑两个方向。如果dp[i][j] < 0则代表这个人走到此处挂了,那我们需要将dp[i][j]赋一个很小的值,如果这个值不够小,可能会导致后面的判断出错(可能会死而复生)。最后将这个人到达四个出口时最大的血量跳出来,如果是负数就代表肯定要挂输出-1即可,否则就输出最大血量的那个值。