虽然上学期暑假的时候做过。那时是在学母函数的时候,今天看到这题的时候,第一反应却是DP。。
给出两种代码吧。 还是第一次接触二进制优化背包
第一:多重背包+二进制优化
#include <cstdlib>
#include <iostream>
using namespace std;
int v[52];
int m[52];
int f[155002];
int n,total,half;
int Max(int a,int b)
{
return (a>b)?a:b;
}
void ZeroOnePake(int v)
{
for(int i=half;i>=v;i--)
f[i]=Max(f[i],f[i-v]+v);
}
void CompletePake(int v)
{
for(int i=v;i<=half;i++)
f[i]=Max(f[i],f[i-v]+v);
}
void solve(int v,int m) //算法的核心
{
if(v*m>=half){CompletePake(v);return;}
int k=1;
while(k<m)
{
ZeroOnePake(k*v);
m-=k;
k<<1;
}
ZeroOnePake(m*v);
}
int main()
{
while(~scanf("%d",&n)&&n>=0)
{
if(n==0){printf("0 0\n");continue;}
total=0;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&v[i],&m[i]);
total+=v[i]*m[i];
}
half=total/2;
for(int i=0;i<=total;i++) f[i]=0;
for(int i=1;i<=n;i++)
solve(v[i],m[i]);
printf("%d %d\n",total-f[half],f[half]);
}
return 0;
}
第二种:母函数
#include"stdio.h"
#include<string.h>
int c1[130000],c2[130000];
int main()
{
struct A
{
int v;
int n;
}E[55];
int total;
int aim;
int i,j,k;
int n;
while(scanf("%d",&n),n>=0)
{
if(n==0) continue;
total=0;
for(i=1;i<=n;i++)
{
scanf("%d%d",&E[i].v,&E[i].n);
total+=E[i].v*E[i].n;
}
aim=total/2;
memset(c2,0,sizeof(c2));
memset(c1,0,sizeof(c1));
for(j=0,k=0;k<=E[1].n;k++,j+=E[1].v) c1[j]=1;
for(i=2;i<=n;i++)
{
for(j=0;j<=aim;j++)
{
if(c1[j]==0) continue;
for(k=0;k<=E[i].n;k++)
c2[k*E[i].v+j]+=c1[j];
}
for(j=0;j<=aim;j++)
{
c1[j]=c2[j];
c2[j]=0;
}
// memset(c2,0,sizeof(c2));
}
for(i=aim;i>=0;i--) if(c1[i]!=0) break;
printf("%d %d\n",total-i,i);
}
return 0;
}