背包系列练习( hdu 2844 Coins && hdu 2159 && poj 1170 Shopping Offers && hdu 3092 Least common multiple && poj 1015 Jury Compromise)

作为一个oier,以及大学acm党背包是必不可少的一部分。好久没做背包类动规了。久违地练习下-。-

dd__engi的背包九讲:http://love-oriented.com/pack/

鸣谢http://blog.csdn.net/eagle_or_snail/article/details/50987044,这里有大部分比较有趣的dp练手题。

hdu 2844 Coins 多重背包

就是一个10w的多重背包,每个物品的cost同时也作为value去做背包,我们求的是每个容量下的价值,所以没法做背包九讲里提到的对最终目标的常数优化。那么我们做完以后,统计一下背包里dp[i]==i的空间i总数即为答案。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #define clr(x) memset(x,0,sizeof(x))
 5 #define MAXN 100010
 6 using namespace std;
 7 int dp[MAXN];
 8 struct node
 9 {
10     int num,cost;
11 }good[MAXN];
12 int n,m,s,t,l,k,ans;
13 int max(int a,int b)
14 {
15     return a>b?a:b;
16 }
17 void zeroonepack(int cost,int val)
18 {
19     for(int i=m;i>=cost;i--)
20     {
21         dp[i]=max(dp[i],dp[i-cost]+val);
22     }
23     return ;
24 }
25 void completepack(int cost,int val)
26 {
27     for(int i=cost;i<=m;i++)
28     {
29         dp[i]=max(dp[i],dp[i-cost]+val);
30     }
31     return ;
32 }
33 void multipack(int cost,int val,int num)
34 {
35     if(cost*num>=m)
36     {
37         completepack(cost,val);
38     }
39     else
40     {
41         int t=1;
42         while(t<=num)
43         {
44             zeroonepack(t*cost,t*val);
45             num-=t;
46             t*=2;
47         }
48         zeroonepack(num*cost,num*val);
49     }
50     return ;
51 }
52 int main()
53 {
54     while(scanf("%d%d",&n,&m)!=EOF && m!=0 && n!=0)
55     {
56         clr(dp);
57         for(int i=1;i<=n;i++)
58         {
59             scanf("%d",&good[i].cost);
60         }
61         for(int i=1;i<=n;i++)
62         {
63             scanf("%d",&good[i].num);
64         }
65         for(int i=1;i<=n;i++)
66         {
67             multipack(good[i].cost,good[i].cost,good[i].num);
68         }
69         ans=0;
70         for(int i=1;i<=m;i++)
71         {
72             if(dp[i]==i)
73                 ans++;
74         }
75         printf("%d\n",ans);
76     }
77     return 0;
78 }

多重背包

hdu 2159 FATE 完全背包

一个二维完全背包,将消耗忍耐度和杀怪数作为二维的cost,然后将求解每个忍耐度和杀怪数下经验值的最大值作为最大价值。我们做一遍二维完全背包,然后找杀怪数满(即dp[s][i])时最小的经验值超过升级所需经验值n的i,这个i即为最小忍耐度,然后m-i即为答案。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #define clr(x) memset(x,0,sizeof(x))
 5 #define MAXN 110
 6 using namespace std;
 7 int dp[MAXN][MAXN],v[MAXN],c[MAXN];
 8 int n,m,k,s,t,l,ans,minn;
 9 int max(int a,int b)
10 {
11     return a>b?a:b;
12 }
13 int main()
14 {
15     while(scanf("%d%d%d%d",&n,&m,&k,&s)!=EOF)
16     {
17         clr(dp);
18         for(int i=1;i<=k;i++)
19         {
20             scanf("%d%d",&v[i],&c[i]);
21         }
22         for(int i=1;i<=k;i++)
23         {
24             for(int j=1;j<=s;j++)
25             {
26                 for(int t=c[i];t<=m;t++)
27                     dp[j][t]=max(dp[j][t],max(dp[j-1][t],dp[j-1][t-c[i]]+v[i]));
28             }
29         }
30         if(dp[s][m]<n)
31         {
32             printf("-1\n");
33         }
34         else
35         {
36                 minn=m;
37                 for(int i=0;i<=m;i++)
38                     if(dp[s][i]>=n && i<minn)
39                     {
40                         minn=i;
41                         break;
42                     }
43                 printf("%d\n",m-minn);
44         }
45     }
46     return 0;
47 }

二维完全背包

poj 1170 Shopping Offers 状压+完全背包

最多五个物品,每个物品最多五件。因此可以将每个状态,cost,最终状态压缩成五位的六进制数,然后做求最小值的完全背包就行了。当然这题还是用编号的形式给出物品的,你需要把物品弄成连续的编号再做压缩操作。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #define clr(x) memset(x,0,sizeof(x))
 5 #define clrmax(x) memset(x,0x3f3f3f3f,sizeof(x))
 6 #define MAXN 1000010
 7 using namespace std;
 8 int dp[MAXN];
 9 int v[MAXN],c[MAXN];
10 int inf[MAXN];
11 int bit(int n)
12 {
13     int l=1;
14     n--;
15     while(n--)
16         l*=6;
17     return l;
18 }
19 bool infer(int i,int j)
20 {
21     while(j)
22     {
23         if(i%6<j%6)
24             return false;
25         i/=6;
26         j/=6;
27     }
28     return true;
29 }
30 int main()
31 {
32     int n,m,maxn,ans,t,k,l,r,cnt,flag,num;
33     while(scanf("%d",&n)!=EOF)
34     {
35         m=0;
36         clr(inf);
37         clrmax(dp);
38         for(int i=1;i<=n;i++)
39         {
40             scanf("%d",&k);
41             inf[k]=i;
42             c[i]=bit(i);
43             scanf("%d%d",&num,&v[i]);
44             m+=bit(i)*num;
45         }
46         cnt=n;
47         scanf("%d",&k);
48         for(int i=1;i<=k;i++)
49         {
50             scanf("%d",&l);
51             flag=0;
52             r=0;
53             for(int i=1;i<=l;i++)
54             {
55                 scanf("%d%d",&n,&t);
56                 if(inf[n]==0 || flag==1)
57                 {
58                     flag=1;
59                     continue;
60                 }
61                 r+=bit(inf[n])*t;
62             }
63             if(flag==0)
64             {
65                 c[++cnt]=r;
66                 scanf("%d",&v[cnt]);
67             }
68             else
69             {
70                 scanf("%d",&r);
71             }
72         }
73         dp[0]=0;
74         for(int i=1;i<=cnt;i++)
75         {
76             for(int j=c[i];j<=m;j++)
77             if(infer(j,c[i]))
78             {
79                 dp[j]=min(dp[j],dp[j-c[i]]+v[i]);
80             }
81         }
82         printf("%d\n",dp[m]);
83     }
84     return 0;
85 }

状压完全背包

时间: 2024-10-16 18:42:40

背包系列练习( hdu 2844 Coins && hdu 2159 && poj 1170 Shopping Offers && hdu 3092 Least common multiple && poj 1015 Jury Compromise)的相关文章

POj 1170 Shopping Offers(变形背包+进制优化) 100

商店买东西会有优惠政策,使用优惠政策使顾客花的钱尽可能的少. 这道题很有现实背景啊,起初看这道题想的是用规则去优化各种组合情况的物品,并没有想到用背包.因为没有做过"规则"这种物品 还有一点就是接收输入信息的时候若用高维数组很难控制,当时竟然写出了int (*it)[5][5][5][5] 这种东西. 这时,进制优化发挥作用了,其思想类似于康托展开,且因为这个问题并不是直接将位置映射到数集,而是各个不同物品的映射.六进制就够用了.将各个物品映射到一个六进制数字中的每一位,一位上的数字0

HDU 2844 Coins (组合背包)

题意   给你n种面额不同的金币和每种金币的个数  求这些金币能组合成的面额在m内有多少种 还是明显的背包问题  d[i]表示这些金币在i内能组合成的最大面额  初始化d为负无穷  d[0]=0  这样就可以保证d[i]恰好为i时才能为正值 原因可以自己想想  然后就用背包背吧  直接多重背包也可以过  但是分成多重背包和完全背包要快一点 #include<cstdio> #include<cstring> #include<algorithm> using names

HDU 2844 Coins (动规)

Coins Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 6904    Accepted Submission(s): 2809 Problem Description Whuacmers use coins.They have coins of value A1,A2,A3...An Silverland dollar. One

HDU 2844 Coins

Problem Description Whuacmers use coins.They have coins of value A1,A2,A3...An Silverland dollar. One day Hibix opened purse and found there were some coins. He decided to buy a very nice watch in a nearby shop. He wanted to pay the exact price(witho

HDU 2844 Coins (多重背包计数 空间换时间)

Coins Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 8999    Accepted Submission(s): 3623 Problem Description Whuacmers use coins.They have coins of value A1,A2,A3...An Silverland dollar. One

hdu 2844 Coins 多重背包模板题 ,二进制优化。据说是楼教主的男人八题之一

Coins Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 8052    Accepted Submission(s): 3291 Problem Description Whuacmers use coins.They have coins of value A1,A2,A3...An Silverland dollar. One

HDU 2844 Coins 多重背包(二进制优化)

点击打开链接 Coins Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 8167    Accepted Submission(s): 3327 Problem Description Whuacmers use coins.They have coins of value A1,A2,A3...An Silverland dolla

HDU 2844 Coins【多重背包】

大意: 有n种物品 告诉你每种物品的价值和数量 问你能拼凑出1--m之内的多少个数 分析: 多重背包 代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 const int maxn = 100005; 7 int dp[maxn]; 8 int num[maxn], va[maxn]; 9 int vo[maxn]; 10 int n

HDu -2844 Coins多重背包

这道题是典型的多重背包的题目,也是最基础的多重背包的题目 题目大意:给定n和m, 其中n为有多少中钱币, m为背包的容量,让你求出在1 - m 之间有多少种价钱的组合,由于这道题价值和重量相等,所以就是dp[i] = i, 其中dp[i]表示当前背包容量为i 的时候背包能装的价值. 题目思路: 模板 二进制优化 话说那个二进制真的很奇妙,只需要2的1次方 到 2的k-1次方, 到最后在加上一项当前项的个数 - 2 的k次方 + 1,也就是这些系数分别为1; 2; 22 .....2k-1;Mi