#include <stdio.h> #define N 125005 int max(int a,int b) { return a>b? a:b; } int f[N]; int main () { int n,c[1001],m[1001],i,j,k,v,sum,t,t1; while(scanf("%d",&n),n>0) { sum=0; for (i=0;i<n;i++) { scanf("%d%d",c+i,m+i); sum+=c[i]*m[i]; } v=sum/2; for (i=0;i<=v;i++) f[i]&=0; for (i=0;i<n;i++) { t=1; for (j=1;t<=m[i];j=j<<1,t+=j)//总的个数(t)小于m[i] { t1=j*c[i]; for (k=v;k>=t1;k--) { f[k]=max(f[k],f[k-t1]+t1); } } if (t<m[i]) { t1=j*c[i]; for (k=v;k>=c[i];k--) { f[k]=max(f[k],f[k-t1]+t1); } } } printf("%d %d/n",sum-f[v],f[v]); } } 优化 当count*cost大于背包大小v时向完全背包转化 #include <stdio.h> #define N 125005 #define M 1001 #define Max(a,b) (a>b? a:b) int c[M],m[M]; int v; int f[N]; void ZeroOnePack(int c,int w) { int i; for (i=v;i>=c;i--) f[i]=Max(f[i],f[i-c]+w); } void CompletePack(int c,int w) { int i; for (i=c;i<=v;i++) f[i]=Max(f[i],f[i-c]+w); } void MulPack(int c,int w,int count) { int i=1; if (count*c>=v) { CompletePack(c,w); return; } else { while(i<count) { ZeroOnePack(i*c,i*w); count-=i; i<<=1; } ZeroOnePack(count*c,count*w); } } int main () { //freopen("1171.txt","r",stdin); int n,i,j,sum; while(scanf("%d",&n),n>0) { sum=0; for (i=0;i<n;i++) { scanf("%d%d",c+i,m+i); sum+=c[i]*m[i]; } v=sum/2; for (i=0;i<=v;i++) f[i]&=0; for (i=0;i<n;i++) MulPack(c[i],c[i],m[i]); printf("%d %d/n",sum-f[v],f[v]); } }