CF999F Solution

题目链接

题解

可以发现,对于每个人来说,除了他最喜欢的数字以外,分配到的其他数字都不重要。因此本题的重点便是如何将若干个同样数字的卡牌分配到喜欢该数字的人,使愉悦值最大,显然可以用dp解决。

状态:\(dp[i][j]\):前\(i\)个人取了\(j\)张牌时的最大愉悦值。

转移方程:\(dp[i][j]=max(dp[i-1][j-t]+h[t])\quad1\le t\le j\)

上述方程的时间复杂度为\(O(n^2k^2)\),可以通过。

此外,因为无论是什么数字的卡牌,获得愉悦值的规则都是相同的,所以可以共用一个\(dp\)数组。易得对于数字\(m\)来说,设\(m\)出现的次数\(i\),喜欢\(m\)的人数为\(j\),可获得的愉悦值为\(dp[i][j]\)

AC代码

#include<bits/stdc++.h>
const int N=510,K=15,C=1e5+10;
int c[N*K],f[N],h[K];
int sumc[C],sumf[C],dp[N][N*K];//dp[i][j]:前i个人取了j张牌时的最大愉悦值。
using namespace std;
int main()
{
	int n,k,maxn=0,ans=0;
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n*k;i++) 
	{
		scanf("%d",&c[i]); 
		sumc[c[i]]++; maxn=max(maxn,c[i]);
	}
	for(int i=1;i<=n;i++) {scanf("%d",&f[i]); sumf[f[i]]++;}
	for(int i=1;i<=k;i++) scanf("%d",&h[i]);
    //计算dp数组
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n*k;j++)
			for(int p=1;p<=min(j,k);p++) dp[i][j]=max(dp[i][j],dp[i-1][j-p]+h[p]);
	//统计答案
    for(int i=1;i<=maxn;i++) ans+=dp[sumf[i]][sumc[i]];
	printf("%d",ans);
	return 0;
}
posted @ 2021-01-03 22:28  violet_holmes  阅读(82)  评论(0编辑  收藏  举报