题目大意
有n个人n*m张牌,每个人分m张牌。每个人有一个自己喜欢的数值,如果他的牌中有x张数值等于这个值则他的高兴度为L[x],求怎样分配牌可以使得所有人的总高兴度最大。
分析
我们发现每一个人只有他喜欢的值对他有影响。所以我们统计出喜欢值x的人有多少和有多少值为x的牌,对于每一个x设dp[i][j]表示考虑了喜欢x的人中的前i个给他们分配j张值为x的牌的最大高兴度。最后的答案就是所有不同x的最终dp值的和。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
int a[10000],sum,L[10000],apr[100100],tot[10000],dp[502][5002],v[510];
int main(){
int n,m,i,j,k;
scanf("%d%d",&n,&m);
for(i=1;i<=n*m;i++)
scanf("%d",&a[i]);
for(i=1;i<=n;i++){
int x;
scanf("%d",&x);
if(!apr[x]){
sum++;
apr[x]=sum;
}
v[apr[x]]++;
}
for(i=1;i<=m;i++)
scanf("%d",&L[i]);
for(i=1;i<=n*m;i++)
if(apr[a[i]])
tot[apr[a[i]]]++;
int ans=0;
for(int _=1;_<=sum;_++){
memset(dp,-0x3f,sizeof(dp));
dp[0][0]=0;
int t=v[_];
for(i=1;i<=t;i++)
for(j=0;j<=min(tot[_],i*m);j++)
for(k=0;k<=min(j,m);k++)
dp[i][j]=max(dp[i][j],dp[i-1][j-k]+L[k]);
ans+=dp[t][min(tot[_],t*m)];
}
printf("%d
",ans);
return 0;
}