首页 > 代码库 > 【板+背包】多重背包 HDU Coins

【板+背包】多重背包 HDU Coins

http://acm.hdu.edu.cn/showproblem.php?pid=2844

【题意】

  • 给定n种价值为Ci,个数为Wi的硬币,问在1~V中的这些数中哪些数能由这些硬币组成?

【思路】

  • 多重背包,二进制优化,时间复杂度为O(V*log∑ni)

【Accepted】

技术分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<string>
 6 #include<algorithm>
 7 #include<queue>
 8 #include<vector>
 9 
10 using namespace std;
11 typedef long long ll;
12 const int maxn=1e5+2;
13 
14 int n,v;
15 int c[maxn],w[maxn];
16 int dp[maxn];
17 void ZOP(int cost,int wei)
18 {
19     for(int i=v;i>=cost;i--)
20     {
21         dp[i]=max(dp[i],dp[i-cost]+wei);    
22     }    
23 } 
24 
25 void CPP(int cost,int wei)
26 {
27     for(int i=cost;i<=v;i++)
28     {
29         dp[i]=max(dp[i],dp[i-cost]+wei);
30     }
31 }
32 
33 void MTP(int cost,int wei,int cnt)
34 {
35     if(v<=cnt*cost)
36     {
37         CPP(cost,wei);
38         return;
39     }
40     int k=1;
41     while(k<=cnt)
42     {
43         ZOP(k*cost,k*wei);
44         cnt-=k;
45         k*=2;
46     }
47     ZOP(cnt*cost,cnt*wei);
48 }
49 int main()
50 {
51     while(~scanf("%d%d",&n,&v))
52     {
53         if(n==0&&v==0) break;
54         for(int i=0;i<n;i++)
55         {
56             scanf("%d",&c[i]);
57         }
58         for(int i=0;i<n;i++)
59         {
60             scanf("%d",&w[i]);
61         }
62         memset(dp,0,sizeof(dp));
63         for(int i=0;i<n;i++)
64         {
65             MTP(c[i],c[i],w[i]);
66         }
67         int cnt=0;
68         for(int i=1;i<=v;i++)
69         {
70             if(dp[i]==i)
71             {
72                 cnt++;
73             }
74         }
75         printf("%d\n",cnt);
76     }
77     return 0;
78 }
背包模板

 

【板+背包】多重背包 HDU Coins