Codeforces Round #490 (Div. 3) :F. Cards and Joy(组合背包)

本文分析了CodeForces 999F题目的解题思路,该题涉及n个人玩游戏,每人获得k张卡片,每张卡片上有一个数字,目标是通过合理的卡片分配最大化欢乐值。文章采用组合背包的方法解决此问题,并提供了详细的代码实现。

题目连接:http://codeforces.com/contest/999/problem/F

解题心得:

  • 题意说的很复杂,就是n个人玩游戏,每个人可以得到k张卡片,每个卡片上有一个数字,每个人有一个喜欢的数字,每一个玩游戏的人如果有不同数量自己喜欢的卡片就有不同的欢乐值。问怎样分配使欢乐值最大。
  • 就是一个组合背包的问题,dp[i][j]代表有i个人,j张喜欢的卡片,得到的总欢乐值最大是多少。在转移的过程中只需要枚举第i个人有几张自己最喜欢的卡片就可以了。
  • 转移方程式dp[i][j] = max(dp[i-1][j-k]+hz[k], dp[i][j])
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn = 510;
 5 const int maxm = 5010;
 6 
 7 ll dp[maxn][maxm],n,k,ht[20],card[maxm],favorite[maxn],ht1[20];
 8 map <int,int> maps;
 9 map <int,int> cnt_card;
10 
11 void init() {
12     scanf("%lld%lld",&n,&k);
13     for(int i=1;i<=k*n;i++) {
14         scanf("%lld", &card[i]);
15         cnt_card[card[i]]++;
16     }
17     for(int i=1;i<=n;i++) {
18         scanf("%lld", &favorite[i]);
19         maps[favorite[i]]++;
20     }
21     for(int i=1;i<=k;i++)
22         scanf("%lld",&ht[i]);
23 }
24 
25 void DP() {
26     for(int i=1; i<=n; i++) {
27         for (int z = 1; z <= k; z++) {
28             for (int j = n * k; j >= 1 ; j--) {
29                 if(z > j)
30                     break;
31                 dp[i][j] = max(dp[i][j], dp[i - 1][j - z] + ht[z]);
32             }
33         }
34     }
35 }
36 
37 int main() {
38     init();
39     DP();
40     map <int,int> :: iterator iter;
41     ll ans = 0;
42     for(iter=maps.begin();iter!=maps.end();iter++) {
43         int num = iter->first;
44         int cnt = iter->second;
45         ll cnt_fav;
46         if(cnt_card[num] > cnt*k){
47             cnt_fav = cnt*k;
48         } else {
49             cnt_fav = cnt_card[num];
50         }
51         ans += dp[cnt][cnt_fav];
52     }
53     printf("%lld",ans);
54     return 0;
55 }

 

转载于:https://www.cnblogs.com/GoldenFingers/p/9281032.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值