P1541 [NOIP2010 提高组] 乌龟棋

题意:

\(n\)张卡片,每张卡片数字为\(1,2,3,4\),有张棋谱,从\(1-n\),从\(1\)出发,到达\(n\),每个位置会有一个分数,你可以安排卡片的顺序,每次拿一张卡片,你就会向前走卡片上面的数字步,然后得到该位置的分数,问如何安排到达\(n\)的时候分数最大(每种卡片最多40张,保证所有卡片之和刚好到达\(n\)点)。

题解:

一开始觉得是01背包裸题,枚举选择的卡片和所在位置,但好像不行?这题是个卡片的顺序有关,而背包问题是选或不选,题目上面说每张卡片最多40张,那么可以开四维DP,每一维表示一种卡片的数目,那么每一种方案的状态有四种情况转移过来,即最后选择的是四种中的哪一种?取max就可以了,转移时保证每一种必须存在至少一张。也对应DP的原理,没有后效性,最开始那种DP,是有后效性的,因为到达第\(pos\)的位置,所剩的卡片可能不一样,但是枚举卡片不管前面是怎么排列的,用完这几张卡片到达的位置是相同的,且剩余的卡片也是相同的。

#include "bits/stdc++.h"
using namespace std;
const int N=42;
int n,m,dp[N][N][N][N],w[505],x,ans,cnt[5];
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)	cin>>w[i];
	for(int i=1;i<=m;i++){
		cin>>x;cnt[x]++;
	}	 
	dp[0][0][0][0]=w[1];
	for(int i=0;i<=cnt[1];i++)
	for(int j=0;j<=cnt[2];j++)
	for(int k=0;k<=cnt[3];k++)
	for(int c=0;c<=cnt[4];c++){
		int ans=0;int ok=0;
		if(i!=0)	ans=max(ans,dp[i-1][j][k][c]);
		if(j!=0)	ans=max(ans,dp[i][j-1][k][c]);
		if(k!=0)	ans=max(ans,dp[i][j][k-1][c]);
		if(c!=0)	ans=max(ans,dp[i][j][k][c-1]);
		dp[i][j][k][c]=max(ans+w[1+i+2*j+3*k+4*c],dp[i][j][k][c]);
	}
	cout<<dp[cnt[1]][cnt[2]][cnt[3]][cnt[4]];
	
	return 0;
}
posted @ 2021-02-17 23:32  喜欢李知恩IU  阅读(96)  评论(0)    收藏  举报