【动态规划】洛谷_1541 乌龟棋

本文探讨了一种使用动态规划解决特定问题的方法,即在有限的卡片组合下,通过不同顺序使用卡片来最大化经过格子上的分数总和。文章详细介绍了状态定义、状态转移方程,并提供了一个C++实现的代码示例。

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

题意

给出NNN个格子,上面有一些分数,有MMM张卡片,每张卡片上标有1,2,3,41,2,3,41,2,3,4这些数字中其中一个,代表使用这张卡片能前进那么多格,每张卡片只能使用一次。
使用不同顺序的卡片可以获得不同的分数,求最大分数。

思路

动态规划。
F[a][b][c][d]F[a][b][c][d]F[a][b][c][d]代表第一种牌用了aaa张,第二种牌用了bbb张,第三……的最大分数,可以得出动态转移方程:
F[a+1][b][c][d]=max(f[a+1][b][c][d],f[a][b][c][d]+A[t])F[a+1][b][c][d]=max(f[a+1][b][c][d],f[a][b][c][d]+A[t])F[a+1][b][c][d]=max(f[a+1][b][c][d],f[a][b][c][d]+A[t])
F[a][b+1][c][d]=max(f[a][b+1][c][d],f[a][b][c][d]+A[t])F[a][b+1][c][d]=max(f[a][b+1][c][d],f[a][b][c][d]+A[t])F[a][b+1][c][d]=max(f[a][b+1][c][d],f[a][b][c][d]+A[t])
……
其中A[t]A[t]A[t]代表使用那么多卡片之后到达的格子上的分数。

代码

#include<cstdio>
#include<algorithm>

int N, M;
int A[351], B[121], F[41][41][41][41], sum[5];

int main() {
	scanf("%d %d", &N, &M);
	for (int i = 1; i <= N; i++)
		scanf("%d", &A[i]);
	for (int i = 1; i <= M; i++) {
		scanf("%d", &B[i]);
		sum[B[i]]++;
	}
	F[0][0][0][0] = A[1];
	for (int a = 0; a <= sum[1]; a++) 
		for (int b = 0; b <= sum[2]; b++)
			for (int c = 0; c <= sum[3]; c++)
				for (int d = 0; d <= sum[4]; d++) {
					int t = a * 1 + b * 2 + c * 3 + d * 4 + 1;
					F[a + 1][b][c][d] = 
						std::max(F[a + 1][b][c][d], F[a][b][c][d] + A[t + 1]);
					F[a][b + 1][c][d] = 
						std::max(F[a][b + 1][c][d], F[a][b][c][d] + A[t + 2]);
					F[a][b][c + 1][d] = 
						std::max(F[a][b][c + 1][d], F[a][b][c][d] + A[t + 3]);
					F[a][b][c][d + 1] = 
						std::max(F[a][b][c][d + 1], F[a][b][c][d] + A[t + 4]);
				}
	printf("%d", F[sum[1]][sum[2]][sum[3]][sum[4]]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值