Codeforces 999F Cards and Joy(二维DP)
题目链接:http://codeforces.com/problemset/problem/999/F
题目大意:
有n个人,n*k张卡牌,每个人会发到k张卡牌,每个人都有一种喜欢的卡牌f[i],当一个人拥有x张喜欢的卡牌时会增加
h[x]点愉悦值,求合理的发牌方式使得所有人的愉悦值之和最大,输出最大愉悦值。
解题思路:
设dp[x][y]表示当x个人拥有同一种喜欢的卡牌且该卡牌有y张时的最大愉悦值。
则状态转移的根本取决于第x个人拥有几张喜欢的卡牌,所以得到状态转移方程:
for (int i = 0; i <= min(k,y); ++i) dp[x][y] = max(dp[x - 1][y], dp[x-1][y-i] + h[i])
代码
1 #include<bits/stdc++.h> 2 #define lc(a) (a<<1) 3 #define rc(a) (a<<1|1) 4 #define MID(a,b) ((a+b)>>1) 5 #define fin(name) freopen(name,"r",stdin) 6 #define fout(name) freopen(name,"w",stdout) 7 #define clr(arr,val) memset(arr,val,sizeof(arr)) 8 #define _for(i,start,end) for(int i=start;i<=end;i++) 9 #define FAST_IO ios::sync_with_stdio(false);cin.tie(0); 10 using namespace std; 11 typedef long long LL; 12 const int N=1e5+5; 13 const int INF=0x3f3f3f3f; 14 const double eps=1e-10; 15 16 int dp[505][5005],f[N],c[N],h[11]; 17 18 int main(){ 19 FAST_IO; 20 int n,k; 21 cin>>n>>k; 22 int x; 23 for(int i=1;i<=n*k;i++){ 24 cin>>x; 25 c[x]++; 26 } 27 for(int i=1;i<=n;i++){ 28 cin>>x; 29 f[x]++; 30 } 31 for(int i=1;i<=k;i++){ 32 cin>>h[i]; 33 } 34 for(int i=1;i<=n;i++){ 35 for(int j=1;j<=n*k;j++){ 36 for(int t=1;t<=min(j,k);t++){ 37 dp[i][j]=max(dp[i][j],dp[i-1][j-t]+h[t]); 38 } 39 } 40 } 41 int ans=0; 42 for(int i=1;i<N;i++){ 43 ans+=dp[f[i]][c[i]]; 44 } 45 cout<<ans<<endl; 46 return 0; 47 }