999F Cards and Joy

传送门

题目大意

有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\n",ans);
      return 0;
}

猜你喜欢

转载自www.cnblogs.com/yzxverygood/p/9485559.html