HDU 1171 Big Event in HDU

 

题意:共N种物品,每种价值为V且共有M件。要求分成两份,使得这两份的价值差最小。

此题是多重背包问题。计算出总价值sum,再除以二得到总价值的一般half。背包容量half,物品的费用和价值均是V。尽量将容量为half的背包填满,则剩下的就是另一部分。

 

代码一(多重背包做法):

 

 

 1 #include<iostream>
 2 using namespace std;
 3 
 4 int sum,half;
 5 int val[55],num[55],f[250005];
 6 
 7 int max(int a,int b){
 8     return a>b?a:b;
 9 }
10 
11 void CompletePack(int v){
12     for(int i=v;i<=half;i++)
13         f[i]=max(f[i],f[i-v]+v);
14 }
15 
16 void ZeroOnePack(int v){
17     for(int i=half;i>=v;i--)
18         f[i]=max(f[i],f[i-v]+v);
19 }
20 
21 void MultiplePack(int v,int m){
22     if(v*m>=half){
23         CompletePack(v);
24         return ;
25     }
26     int k=1;
27     while(k<=m){
28         ZeroOnePack(k*v);
29         m-=k;
30         k<<=1;
31     }
32     ZeroOnePack(m*v);
33 }
34 
35 int main()
36 {
37     int n,i,k;
38     while(scanf("%d",&n),n>-1){
39         for(sum=0,i=1;i<=n;i++){
40             scanf("%d %d",&val[i],&num[i]);
41             sum+=val[i]*num[i];
42         }
43         half=sum/2;
44         for(i=0;i<=half;i++)
45             f[i]=0;
46         for(i=1;i<=n;i++)
47             MultiplePack(val[i],num[i]);
48         printf("%d %d\n",sum-f[half],f[half]);
49     }
50     return 0;
51 }

 

代码二(转化为01背包做法):

 

 

 1 #include<iostream>
 2 using namespace std;
 3 
 4 int f[2500005],val[55],num[55];
 5 
 6 int max(int a,int b){
 7     return a>b?a:b;
 8 }
 9 
10 int main()
11 {
12     //freopen("in.txt","r",stdin);
13     int n,i,j,k,sum,half;
14     while(scanf("%d",&n),n>-1){
15         for(sum=0,i=1;i<=n;i++){
16             scanf("%d %d",&val[i],&num[i]);
17             sum+=val[i]*num[i];
18         }
19         half=sum/2;
20         for(i=0;i<=half;i++)
21             f[i]=0;
22         for(i=1;i<=n;i++){
23             for(j=1;j<=num[i];j++)
24                 for(k=half;k>=val[i];k--)
25                     f[k]=max(f[k],f[k-val[i]]+val[i]);
26         }
27         printf("%d %d\n",sum-f[half],f[half]);
28     }
29     return 0;
30 }

 

 

 

代码三(转化为01背包+二进制优化):

 

 

 1 #include<iostream>
 2 using namespace std;
 3 
 4 int f[2500005],val[55],num[55];
 5 
 6 int max(int a,int b){
 7     return a>b?a:b;
 8 }
 9 
10 int main()
11 {
12     //freopen("in.txt","r",stdin);
13     int n,i,j,k,half,sum;
14     while(scanf("%d",&n),n>-1){
15         for(sum=0,i=1;i<=n;i++){
16             scanf("%d %d",&val[i],&num[i]);
17             sum+=val[i]*num[i];
18         }
19         half=sum/2;
20         for(i=1;i<=half;i++)
21             f[i]=0;
22         for(i=1;i<=n;i++){
23             for(k=1;k<=num[i];num[i]-=k,k<<=1){
24                 for(j=half;j>=val[i]*k;j--)
25                     f[j]=max(f[j],f[j-val[i]*k]+val[i]*k);
26             }
27             if(num[i]){
28                 for(j=half;j>=num[i]*val[i];j--)
29                     f[j]=max(f[j],f[j-num[i]*val[i]]+num[i]*val[i]);
30             }
31         }
32         printf("%d %d\n",sum-f[half],f[half]);
33     }
34     return 0;
35 }

 

 

 

 

 

 

 

 

 

 

 

posted on 2013-03-01 12:55  Acmer_Roney  阅读(163)  评论(0编辑  收藏  举报

导航