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;
}