hdu2844 coins 多重背包

 1 #include<stdio.h>
 2 #include<string.h>
 3 int a[102],c[102],dp[100005];
 4 int max(int a,int b)
 5 {
 6     return a>b?a:b;
 7 }
 8 void CompletePack(int v,int w,int m) //完全背包
 9 {
10      for(int j=v;j<=m;j++)
11       dp[j]=max(dp[j],dp[j-v]+w);
12 }
13 void ZeroOnePack(int v,int w,int m) //01背包
14 {
15       for(int j=m;j>=v;j--)
16        dp[j]=max(dp[j],dp[j-v]+w);
17 }
18 void MultiPack(int v,int w,int m,int c) //多重背包
19 {
20     if(v*c>=m) //体积乘以数量大于总体积,说明不能完全装完,相当于有无穷件,用完全背包
21      CompletePack(v,w,m);
22     else  //可以装完,用01背包
23     {
24         int k=1;
25         while(k<c) //二进制优化
26         {
27             ZeroOnePack(k*v,k*w,m);
28              c-=k;
29              k*=2;
30         }
31         ZeroOnePack(c*v,c*w,m);
32     }
33 }
34 int main()
35 {
36     int n,i,j,m,k;
37     while(scanf("%d%d",&n,&m)!=EOF)
38     {
39         if(n==0&&m==0) break;
40         for(i=0;i<n;i++)
41          scanf("%d",&a[i]);  //a[i]既是物体的体积,又是物体的价值
42         for(i=0;i<n;i++)
43          scanf("%d",&c[i]); //c[i]是物体的数量
44         memset(dp,0,sizeof(dp));
45         for(i=0;i<n;i++)
46         {
47             MultiPack(a[i],a[i],m,c[i]);
48         }
49         int count=0; //计数
50         for(i=1;i<=m;i++)
51          if(dp[i]==i)  //可以组合且不用找钱
52           count++;
53         printf("%d\n",count);
54     }
55     return 0;
56 }
代码君

 

posted @ 2014-12-13 23:48  UsedRose  阅读(126)  评论(0编辑  收藏  举报