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;
}
要拿牌啊

浙公网安备 33010602011771号