http://acm.hdu.edu.cn/showproblem.php?pid=1171
题意:已知有N种价值的物品,每种价值为v,有m件,现将物品分为两部分,使每部分价值尽量相等(如果不等则使第一部分大于第二部分)。
多重背包:
思路:背包体积为总价值的一半,然后用多重背包求最大值。
#include<stdio.h> #include<string.h> int bag[333333]; int main() { int n,w[555]; while(scanf("%d",&n)&&(n>=0)) { int i,j,sum=0,size,k=1;; for(i=1;i<=n;i++) { int tmp,v,m; scanf("%d %d",&v,&m); sum+=v*m; tmp=1; while(m>tmp) { w[k++]=tmp*v; m-=tmp; tmp<<=1; } w[k++]=m*v; } size=sum/2; memset(bag,0,sizeof(bag)); for(i=1;i<k;i++) for(j=size;j>=w[i];j--) if(bag[j]<bag[j-w[i]]+w[i]) bag[j]=bag[j-w[i]]+w[i]; printf("%d %d\n",sum-bag[size],bag[size]); } return 0; }
母函数:
#include<stdio.h> #include<string.h> int e[1111],elem[1111]; int c1[222222],c2[222222]; int main() { int t,i,j,k; while(scanf("%d",&t)&&t>=0) { int sum=0; for(i=1;i<=t;i++) { scanf("%d %d",&elem[i],&e[i]); sum+=e[i]*elem[i]; } memset(c1,0,sizeof(c1)); memset(c2,0,sizeof(c2)); for(i=0;i<=e[1]*elem[1];i+=elem[1]) c1[i]=1; for(i=2;i<=t;i++) { for(j=0;j<=sum/2;j++) for(k=0;k<=e[i]*elem[i]&&j+k<=sum/2;k+=elem[i]) c2[j+k]+=c1[j]; for(j=0;j<=sum/2;j++) { c1[j]=c2[j]; c2[j]=0; } } for(i=sum/2;i>0;i--) if(c1[i]) break; printf("%d %d\n",sum-i,i); } return 0; }