UVA_10913

    为了保证每个格子只走一遍,所以对于每行,我们都从左往右dp一次,再从右往左dp一次,每个格子取两次dp的最大值即可。

    如果用递推去做的话,f可以初始化成-INF,但注意只有当前的格子不等于-INF时才进行dp,否则如果下一个格子是正值的话,会当做可以到这个格子,并且路径值是-INF。

#include<stdio.h>
#include<string.h>
#define MAXN 80
#define MAXK 10
#define INF 0x3f3f3f3f
int N, K, a[MAXN][MAXN], f[MAXK][MAXN][MAXN], left[MAXK][MAXN], right[MAXK][MAXN];
int init()
{
int i, j;
scanf("%d%d", &N, &K);
if(!N && !K)
return 0;
for(i = 1; i <= N; i ++)
for(j = 1; j <= N; j ++)
scanf("%d", &a[i][j]);
return 1;
}
void solve()
{
int i, j, k, max = -INF;
for(i = 0; i <= K; i ++)
for(j = 1; j <= N; j ++)
for(k = 1; k <= N; k ++)
f[i][j][k] = -INF;
if(a[1][1] < 0)
f[1][1][1] = a[1][1];
else
f[0][1][1] = a[1][1];
for(i = 0; i <= K; i ++)
for(j = 1; j < N; j ++)
if(f[i][1][j] != -INF)
{
if(a[1][j + 1] < 0)
{
if(f[i][1][j] + a[1][j + 1] > f[i + 1][1][j + 1])
f[i + 1][1][j + 1] = f[i][1][j] + a[1][j + 1];
}
else if(f[i][1][j] + a[1][j + 1] > f[i][1][j + 1])
f[i][1][j + 1] = f[i][1][j] + a[1][j + 1];
}
for(k = 2; k <= N; k ++)
{
for(i = 0; i <= K; i ++)
for(j = 1; j <= N; j ++)
if(f[i][k - 1][j] != -INF)
{
if(a[k][j] < 0)
{
if(f[i][k - 1][j] + a[k][j] > f[i + 1][k][j])
f[i + 1][k][j] = f[i][k - 1][j] + a[k][j];
}
else if(f[i][k - 1][j] + a[k][j] > f[i][k][j])
f[i][k][j] = f[i][k - 1][j] + a[k][j];
}
for(i = 0; i <= K; i ++)
for(j = 1; j <= N; j ++)
left[i][j] = right[i][j] = f[i][k][j];
for(i = 0; i <= K; i ++)
for(j = 1; j < N; j ++)
if(left[i][j] != -INF)
{
if(a[k][j + 1] < 0)
{
if(left[i][j] + a[k][j + 1] > left[i + 1][j + 1])
left[i + 1][j + 1] = left[i][j] + a[k][j + 1];
}
else if(left[i][j] + a[k][j + 1] > left[i][j + 1])
left[i][j + 1] = left[i][j] + a[k][j + 1];
}
for(i = 0; i <= K; i ++)
for(j = N; j > 1; j --)
if(right[i][j] != -INF)
{
if(a[k][j - 1] < 0)
{
if(right[i][j] + a[k][j - 1] > right[i + 1][j - 1])
right[i + 1][j - 1] = right[i][j] + a[k][j - 1];
}
else if(right[i][j] + a[k][j - 1] > right[i][j - 1])
right[i][j - 1] = right[i][j] + a[k][j - 1];
}
for(i = 0; i <= K; i ++)
for(j = 1; j <= N; j ++)
f[i][k][j] = left[i][j] > right[i][j] ? left[i][j] : right[i][j];
}
for(i = 0; i <= K; i ++)
if(f[i][N][N] > max)
max = f[i][N][N];
if(max == -INF)
printf("impossible\n");
else
printf("%d\n", max);
}
int main()
{
int t = 0;
while(init())
{
printf("Case %d: ", ++ t);
solve();
}
return 0;
}