关键是思路,为的使两个分组中的值最接近,则只要求出可以取到的最接近最大值一半的那个数,因此将sum/2作为上线
状态转移方程
dp[i]=Max(dp[i-w[j]]+v[j],dp[i]) 注意从最大值开始迭代,(完全背包是从最小值开始迭代)
由于这里没有v数组,因此退化成bool型的值
#include<iostream>
#include<cstring>
#define Max(a,b) (a<b?b:a)
using namespace std;
bool dp[250001];
int val[51];
int num[51];
int N,sum;
int main(){
while(cin>>N&&N>=0){
sum=0;
for(int i=0;i<N;i++){
int v,n;
cin>>v>>n;
val[i]=v;
num[i]=n;
sum+=v*n;
}
memset(dp,0,sizeof(dp));
dp[0]=1;
for(int i=0;i<N;i++){
int mm=val[i]*num[i];
int tmp=val[i];
while(tmp<=mm){
for(int j=sum/2;j>=tmp;j--){
dp[j]=dp[j-tmp];
}
mm=mm-tmp;
tmp=tmp<<1;
}
int leav=mm;
if(leav){
for(int j=sum/2;j>=leav;j--){
dp[j]=dp[j-leav];
}
}
}
int ans=0;
for(int i=sum/2;i>=0;i--){
if(dp[i]){
ans=i;
break;
}
}
cout<<sum-ans<<" "<<ans<<endl;
}
return 0;
}