设d[i][j][k]为走到(i,j)经过k个负数的收益,负无穷表示无法达到这个状态。由于只能向下、左、右且不能走回头路,于是按层DP就好了。注意用long long。
//10913 Walking on a Grid Accepted C++ 0.032 2012-12-10 13:29:24
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 75+5, MAXK = 5+5;
const long long INF = 1LL<<60;
int N, K, g[MAXN][MAXN], cnt[MAXN][MAXN];
long long sum[MAXN][MAXN], d[MAXN][MAXN][MAXK];
int main()
{
for (int cas = 1; scanf("%d%d", &N, &K); cas++)
{
if (!N && !K)
break;
for (int i = 1; i <= N; i++)
for (int j = 1; j <= N; j++)
{
scanf("%d", &g[i][j]);
sum[i][j] = sum[i][j-1]+g[i][j];
cnt[i][j] = cnt[i][j-1]+(g[i][j] < 0 ? 1 : 0);
}
for (int i = 1; i <= N; i++)
for (int j = 1; j <= N; j++)
fill(d[i][j], d[i][j]+K+1, -INF);
for (int j = 1; j <= N && cnt[1][j] <= K; j++)
d[1][j][cnt[1][j]] = sum[1][j];
for (int i = 2; i < N; i++)
for (int j = 1; j <= N; j++)
for (int p = 1; p <= N; p++)
{
int s = (p < j ? sum[i][j]-sum[i][p-1] : sum[i][p]-sum[i][j-1]);
int c = (p < j ? cnt[i][j]-cnt[i][p-1] : cnt[i][p]-cnt[i][j-1]);
for (int k = K; k >= c; k--)
if (d[i-1][p][k-c] > -INF)
d[i][j][k] = max(d[i][j][k], d[i-1][p][k-c]+s);
}
for (int p = 1; p <= N; p++)
{
int s = sum[N][N]-sum[N][p-1];
int c = cnt[N][N]-cnt[N][p-1];
for (int k = K; k >= c; k--)
if (d[N-1][p][k-c] > -INF)
d[N][N][k] = max(d[N][N][k], d[N-1][p][k-c]+s);
}
long long ans = -INF;
for (int k = 0; k <= K; k++)
ans = max(ans, d[N][N][k]);
if (ans > -INF)
printf("Case %d: %lld\n", cas, ans);
else
printf("Case %d: impossible\n", cas);
}
return 0;
}