CodeForces 999F Cards ans Joy
题目
◇题目传送门◆
题目大意
有NN个人,每人要得到 张牌,牌上有不同的数字,记第ii张牌上的数字为 。第ii个人有自己喜欢的数字,记为 。若每个人能够得到ii张自己所喜欢的牌,则能够获得 的快乐值。将每个人所获得的快乐值的总和称为总快乐值,求能获得的最大总快乐值。
思路
非常裸的一道DP题。
我们记f[i][j]f[i][j]为将ii张相同的牌分给 个所获得的最大快乐值。
很容易得出状态转移方程:
f[i][j]={
h[min(i,K)](1≤i≤N×K)max{
f[i?k][j?1]+h[k]}(1≤i≤N×T,2≤j≤N,1≤k≤min(i,K))f[i][j]={max{f[i?k][j?1]+h[k]}(1≤i≤N×T,2≤j≤N,1≤k≤min(i,K))h[min(i,K)](1≤i≤N×K)
我们同时记C[i]C[i]为数值为ii的牌的数量, 为喜欢数值为ii的人数,答案即为:
实现细节
注意:可能会炸int
,请使用long long
。
正解代码
#include<cstdio>
#include<algorithm>
using namespace std;
const int Maxn=500,Maxk=10,Maxnum=1e5;
int N,K;
int cad[Maxn*Maxk+5],peo[Maxn+5],H[Maxk+5];
int C[Maxnum+5],P[Maxnum+5];
int dp[Maxn*Maxk+5][Maxn+5];void ReadIn() {scanf("%d %d",&N,&K);for(int i=1;i<=N*K;i++) {scanf("%d",&cad[i]);C[cad[i]]++;}for(int i=1;i<=N;i++) {scanf("%d",&peo[i]);P[peo[i]]++;}for(int i=1;i<=K;i++)scanf("%d",&H[i]);
}long long GetAns() {long long ret=0;for(int i=0;i<=Maxnum;i++)if(P[i])ret+=dp[C[i]][P[i]];return ret;
}int main() {#ifdef LOACLfreopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#endifReadIn();for(int i=1;i<=N*K;i++) {dp[i][1]=H[min(i,K)];for(int j=2;j<=N;j++)for(int k=1;k<=min(i,K);k++)dp[i][j]=max(dp[i][j],dp[i-k][j-1]+H[k]);}printf("%d\n",GetAns());return 0;
}
Thanks For Reading!
如有不妥之处请在评论中指出,我会尽快回复!