UVA 10913 Walking on a Grid

本文介绍了一个基于动态规划解决网格行走问题的方法,通过计算路径中经过的负数数量及累计收益来寻找最优路径。使用了三维数组存储中间结果,并考虑了边界情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    设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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值