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 阅读(165) 评论(0) 编辑 收藏 举报