P1541-DP【绿】

发布时间 2023-12-08 20:09:45作者: Kai-G

刚开始理解错题意了,题中说“玩家每次需要从所有的爬行卡片中选择一张之前没有使用过的爬行卡片”指的是不能用同一张卡片,我给理解成不能连续用同一种卡片了。后来想想其实题目中的说法歧义不大,是我粗心才导致看错的。
最终我看错的导致了题目难度更高一些,偏偏写完了更高难度的题之后还过不了..直到最后对照样例才发现不对劲,然后稍稍修正就AC了,整体而言这道题用了近两个小时,一点也不快,毕竟题都理解错了肯定多花不少时间。
这道题的收获是:DP的核心在于用尽量少的数据去完整的刻画出状态,尽量少是一个点,另一个点是绝对不应该有任何的冗余数据,即如果某个坐标能被其他坐标计算出来,那显然这个坐标就没有存在的必要了!
最后,上代码

Code

#include <iostream>
#include <cstring>

using namespace std;
int N,M,a[400],x,card[5],dp[41][41][41][41],ans;
int dfs(int c1,int c2,int c3,int c4)
{
	if(c1>card[1]||c2>card[2]||c3>card[3]||c4>card[4])return -99999999;
	if(dp[c1][c2][c3][c4]!=-1)return dp[c1][c2][c3][c4];
	int pos=1+1*(card[1]-c1)+2*(card[2]-c2)+3*(card[3]-c3)+4*(card[4]-c4);
	if(pos==1)return dp[c1][c2][c3][c4]=a[1];
	int tans=0;
	tans=max(tans,dfs(c1+1,c2,c3,c4));
	tans=max(tans,dfs(c1,c2+1,c3,c4));
	tans=max(tans,dfs(c1,c2,c3+1,c4));
	tans=max(tans,dfs(c1,c2,c3,c4+1));
	return dp[c1][c2][c3][c4]=a[pos]+tans;
}

signed main()
{
	memset(dp,-1,sizeof(dp));
	cin>>N>>M;
	for(int i=1;i<=N;i++)cin>>a[i];
	for(int i=1;i<=M;i++)cin>>x,card[x]++;
	cout<<dfs(0,0,0,0)<<endl;
	return 0;
}