题目:http://acm.hdu.edu.cn/showproblem.php?pid=1171
以前做多重背包的问题。都是直接用母函数做的。但是这次不能了- -,因为这个数据有点多。。用母函数肯定要跑很久。要是和上次那个6个数字一样用母函数就好很多了。多重背包问题其实最主要的就是多一次预处理。因为二进制可以表示任意10进制的数。所以通过二进制的思路进行预处理。后来就当做普通的01背包问题就行了。
#include <bits/stdc++.h>
#define INF 1e18
#define inf 1e9
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define IOS ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std ;
typedef long long ll;
typedef unsigned long long ull;
const int _max = 5005;
int p[_max],c[_max];
int np[_max];
int dp[250005];
int main(){
IOS;
int n,sum,sum1,cnt;
while(cin>>n && n>0){
memset(dp,0,sizeof(dp));
memset(np,0,sizeof(np));
sum = 0,cnt = 0,sum1 = 0;
for(int i = 1 ; i <= n ; i++){
cin>>p[i]>>c[i];
sum1 += p[i]*c[i];
}
sum = sum1/2;
for(int i = 1 ; i <= n ; i++){
int t = 1;
while(c[i] >= t){
np[++cnt] = p[i]*t;
c[i] -= t;
t *= 2;
}
if(c[i]) np[++cnt] = p[i]*c[i];
} //二进制优化
sort(np+1,np+cnt+1);
for(int i = 1 ; i <= cnt ; i++){
if(np[i] > sum) break;
for(int j = sum ; j >= np[i] ; j--){
dp[j] = max(dp[j],dp[j-np[i]]+np[i]);
}
}//背包
cout<<sum1-dp[sum]<<' '<<dp[sum]<<endl;
}
return 0;
}