/*
http://acm.hdu.edu.cn/showproblem.php?pid=1171 Big Event in HDU
题意 多重背包 将器材分成两份,尽量平均
*/
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#define CLR(c,v) (memset(c,v,sizeof(c)))
using namespace std;
const int M = 25e4 + 10;
const int INF = 1 << 30;
const int inf = -(1 << 30);
int dp[M]; // dp[i][k] : 第i分组中 消耗为k时 的最优价值
int n[50+10]; // 每种的个数
int v[50+10]; // 每种的价值
void ZeroOnePack(int cost,int value ,int max_cost){
for (int i = max_cost; i >= cost ; i--){
if (dp[i] < dp[i-cost] + value){
dp[i] = dp[i-cost] + value;
}
}
}
void CompletePack(int cost, int value,int max_cost){
for (int i = cost ; i <= max_cost ; i++){
if(dp[i] < dp[i-cost] + value){
dp[i] = dp[i-cost] + value;
}
}
}
void MultiplePack(int cost,int value,int amount,int max_cost){
if (cost*value > max_cost){
CompletePack(cost,value,max_cost);
}else{
for (int k = 1 ; k <= amount ; k <<= 1){
if (k*cost < max_cost){
ZeroOnePack(cost*k , value*k , max_cost);
amount -= k;
}
}
ZeroOnePack(cost*amount , value*amount , max_cost);
}
}
int main(){
//freopen("in.txt","r",stdin);
int n_pack;
while(cin >> n_pack && n_pack>-1){
CLR(dp,0);
int sum = 0;
for (int i = 1 ; i <= n_pack ; i++){
cin >> v[i] >> n[i];
sum += v[i] * n[i];
}
for (int i = 1 ; i <= n_pack ; i++){
MultiplePack(v[i],v[i],n[i],sum >> 1); // 计算最大消耗 不超sum/2的价值
}
cout << sum - dp[sum>>1] << " " << dp[sum>>1] << endl;
}
return 0;
}
HDU Big Event in HDU - 多重背包
最新推荐文章于 2020-09-04 01:51:25 发布