Jeff喜欢玩,贪吃蛇游戏。玩了很多次之后,他对里面的规则感到厌烦。
为了使得游戏更加有趣,他制定了一些新的规则:
1. 地图是由n*m个格子组成的(1 <= n, m <= 1000),n行,m列。
2. 每个格子有一个值vi (-1 ≤ vi≤ 99999),如果vi是-1,那么这个格子不能走,也不能穿过这个格子,如果不是-1,蛇经过这个点之后会获得vi的分数
3. 蛇可以从最左边的任意一个格子出发,他的目的是到达最右侧的某个格子中。
4. 在行走的过程中,蛇只能向上,向下,向右行走,即,当前在第x行,y列时(x,y),只能走到(x+1,y),(x-1,y),(x,y+1),每个格子最多只能经过一次。
其它情况说明:
a.蛇到达最右侧之后还是可以上下走动的。
b.如果蛇在最上面的格子时,他还可以往上面走,走上去之后就被(传送门,teleport)传送到了最下面的格子,并且之前的积分清0。在最下面的格子如果想往下走时,则会被传送到最上面的格子中,积分同样清0。
创建好这个游戏之后, Jeff在想怎么样才能获得最高的分数呢?请你写一个程序帮助他。
样例图解。
样例1![](http://img.51nod.com/upload/000FBEB5/08D262251E0E08D6000000000000000F.png)
样例2
![](http://img.51nod.com/upload/000FBEB5/08D26224F05E4D7E000000000000000D.png)
这儿用了teleport,到了2之后往下走到4。
Input
第一行有两个整数n,m,以一个空格分开。(1 <= n, m <= 1000) 接下来n行给出格子的信息。每一行包括m个整数vi, (-1 ≤ vi ≤ 99999),vi=-1时表示这个格子不能走。
Output
对于每一组数据,输出最高能获得的分数。如果蛇无法到达最右侧,输出-1。
Input示例
4 4 -1 4 5 1 2 -1 2 4 3 3 -1 3 4 2 1 2 4 4 -1 4 5 1 2 -1 2 4 3 3 -1 -1 4 2 1 2
Output示例
23 16
题解:orz神奇dp。具体明天再研究。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
LL read(){
LL x = 0, k = 1; char ch = getchar();
while (ch < '0' || '9' < ch){
if (ch == '-') k = -1;
ch = getchar();
}
while ('0' <= ch && ch <= '9'){
x = x*10 + ch-'0';
ch = getchar();
}
return x*k;
}
const int maxn = 1005;
LL f[maxn][maxn], pf[maxn];
LL g[maxn][maxn], pg[maxn];
LL h[maxn][maxn];
LL v[maxn][maxn];
int n, m; LL ans;
int main(){
while (~scanf("%d%d", &n, &m)){
for (int i=1; i<=n; i++)
for (int j=1; j<=m; j++)
v[i][j] = read();
for (int j=1; j<=m; j++){
f[0][j] = g[n+1][j] = -1e18;
for (int i=1; i<=n; i++)
if (v[i][j] == -1) f[i][j] = -1e18;
else if (h[i][j-1] >= f[i-1][j]) { f[i][j] = h[i][j-1] + v[i][j]; pf[i] = i; }
else { f[i][j] = f[i-1][j] + v[i][j]; pf[i] = pf[i-1]; }
for (int i=n; i>=1; i--)
if (v[i][j] == -1) g[i][j] = -1e18;
else if (h[i][j-1] >= g[i+1][j]) { g[i][j] = h[i][j-1] + v[i][j]; pg[i] = i; }
else { g[i][j] = g[i+1][j] + v[i][j]; pg[i] = pg[i+1]; }
if (g[n][j] >= 0) f[0][j] = 0;
if (f[1][j] >= 0) g[n+1][j] = 0;
for (int i=1; i<=pf[n]-1; i++)
if (v[i][j] >= 0) f[i][j] = max(f[i][j], f[i-1][j]+v[i][j]);
for (int i=n; i>=pg[1]+1; i--)
if (v[i][j] >= 0) g[i][j] = max(g[i][j], g[i+1][j]+v[i][j]);
for (int i=1; i<=n; i++)
h[i][j] = max(f[i][j], g[i][j]);
}
ans = -1;
for (int i=1; i<=n; i++)
ans = max(ans, h[i][m]);
printf("%lld\n", ans);
}
return 0;
}