洛谷P1541 乌龟棋

首先想到状态:f[x][a][b][c][d],表示已用a张一步卡、b张两步卡、c张三步卡、d张四步卡、走到第x格的最大得分。但五维dp容易超空间又容易超时,所以试着对状态进行优化。

我们发现,x用于计算每格的得分;而已知a, b, c, d时,x可求得,所以可以省掉第一维状态。 x = 1 + 1*a + 2*b + 3*c + 4*d (注意此处的1)

状态:f[a][b][c][d]  已用a张一步卡、b张两步卡、c张三步卡、d张四步卡的最大得分

因为输入数据保证到终点时一定用完四种卡片,所以最终状态一定是f[card[1]][card[2]][card[3]][card[4]]

#include<iostream>
#include<cstdio>
#include<algorithm>
#define dp0 dp[a][b][c][d]
using namespace std;

int n,m,card[5],k[400],dp[41][41][41][41];

int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1; i<=n; i++) scanf("%d",&k[i]);
	for (int i=1; i<=m; i++) {
		int p;
		scanf("%d",&p);
		card[p]++;
	}
	for (int a=0; a<=card[1]; a++)
		for (int b=0; b<=card[2]; b++)
			for (int c=0; c<=card[3]; c++)
				for (int d=0; d<=card[4]; d++) {
					dp0 = 0;
					if (a>0) dp0 = max(dp0,dp[(a-1)][b][c][d]); //注意判断a>0!
					if (b>0) dp0 = max(dp0,dp[a][(b-1)][c][d]);
					if (c>0) dp0 = max(dp0,dp[a][b][(c-1)][d]);
					if (d>0) dp0 = max(dp0,dp[a][b][c][(d-1)]);
					dp0 += k[1+a+2*b+3*c+4*d];
				}
	printf("%d",dp[card[1]][card[2]][card[3]][card[4]]);
	return 0;
}

为省空间,可采用循环队列。

因为dp[a][b][c][d]只与dp[a/a-1][b/b-1][c/c-1][d/d-1]有关,所以开数组dp[2][2][2][2]。

循环中dp[a%2][b%2][c%2][d%2]

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值