【二进制优化-多重背包】zznu-oj-2120 : 安详--如何用尽钱币打赏主播获得最大好感度

2120 : 安详

题目描述

spring最近喜欢上了B站新秀主播,身为顿顿吃黄焖鸡的土豪,当然要过去打赏一番,但是spring还是喜欢精打细算,所以在打赏的时候,想要掏出有限的钱,获得主播的最大好感。

主播的好感值是通过送不同的礼物而提升不同,不同礼物的赠送,可以增加的好感值也是不同的,当然礼物的价格更是不同。

输入

输入第一行为两个整数n,m.分别表示有n种不同礼物(1e2)和总金钱数m(1e6),以下n行每行有三个数字,分别表示该礼物的个数(int)和价格(int)以及好感值(int)。 多实例

输出

求spring拿出的钱可以送出的最大好感值。

样例输入

复制
2 10
4 2 100
2 4 100

样例输出

复制
400

多重背包解决思路:

 题目:有N种物品和一个容量为V的背包。第i种物品最多有num[i]件可用,每件容量是c[i],价值是w[i]。

转换成01背包:二进制优化方法是:将第i种物品分成若干件物品,其中每件物品有一个系数,这件物品的容量和价值均是原来的容量和价值乘以这个系数。使这些系数分别为1,2,4,...,2^(k-1),(以及二进制尾数部分)num[i]-2^k+1,且k是满足num[i]-2^k+1>0的最大整数。例如,如果n[i]为13,就将这种物品分成系数分别为1,2,4,6的四件物品。

  

 1 #define N 10008
 2 #define M 1000008
 3 
 4 ll dp[M];
 5 struct node{
 6     ll c,w;  //c为cost,w为好感度
 7 }p[N];
 8 
 9 int main(){
10 
11     ll nn,m;
12     while(scanf("%lld%lld",&nn,&m)!=EOF){
13         int cnt=0;//拆分后的物品数
14         ll t,c,w;
15 
16         for(int i=1;i<=nn;i++){
17             scanf("%lld%lld%lld",&t,&c,&w);  //数量,花费,好感度
18             int x=1;
19             while(t-x>0){
20                 t-=x;
21                 p[++cnt].c=x*c;
22                 p[cnt].w  =x*w;
23                 x*=2;
24             }
25             p[++cnt].c=t*c; //跑完上面的循环后剩下t
26             p[cnt].w=t*w;
27         }
28 
29         memset(dp,0,sizeof(dp));
30         for(int i=1;i<=cnt;i++){
31             for(int j=m;j>=p[i].c;j--){  //花费自大到小
32                 dp[j]=max(dp[j],dp[j-p[i].c]+p[i].w);
33             }
34         }
35 
36 
37         printf("%lld
",dp[m]);
38     }
39 
40     return 0;
41 }
42 #define N 10008
43 #define M 1000008
44 
45 ll dp[M];
46 struct node{
47     ll c,w;  //c为cost,w为好感度
48 }p[N];
49 
50 int main(){
51 
52     ll nn,m;
53     while(scanf("%lld%lld",&nn,&m)!=EOF){
54         int cnt=0;//拆分后的物品数
55         ll t,c,w;
56 
57         for(int i=1;i<=nn;i++){
58             scanf("%lld%lld%lld",&t,&c,&w);  //数量,花费,好感度
59             int x=1;
60             while(t-x>0){
61                 t-=x;
62                 p[++cnt].c=x*c;
63                 p[cnt].w  =x*w;
64                 x*=2;
65             }
66             p[++cnt].c=t*c; //跑完上面的循环后剩下t
67             p[cnt].w=t*w;
68         }
69 
70         memset(dp,0,sizeof(dp));
71         for(int i=1;i<=cnt;i++){
72             for(int j=m;j>=p[i].c;j--){  //花费自大到小
73                 dp[j]=max(dp[j],dp[j-p[i].c]+p[i].w);
74             }
75         }
76 
77 
78         printf("%lld
",dp[m]);
79     }
80 
81     return 0;
82 }
View Code(头文件都私奔找对象去啦!)
原文地址:https://www.cnblogs.com/zhazhaacmer/p/9373008.html