#include<iostream> #include<cstdio> using namespace std; #define MAX(a,b) (a>b)?a:b const int SIZE=100000+16; int nKind; //物品种类数目 int nLimit; //背包容量 int val[SIZE]; //每种背包的价值 int weight[SIZE]; //每种背包的重量 int bag[SIZE]; //每种背包的数目 int dp[SIZE]; //0-1背包, 代价为cost, 获得的价值为value void ZeroOnePack(int cost, int value) { for(int i=nLimit; i>=cost; i--) //逆序 { dp[i]=MAX(dp[i], dp[i-cost]+value); } } //完全背包, 代价为cost, 获得的价值为value void CompletePack(int cost, int value) { for(int i=cost; i<=nLimit; i++) //顺序 { dp[i]=MAX(dp[i],dp[i-cost]+value); } } //多重背包 代价为cost, 获得的价值为value, 该种背包的数目为amount void MultiplyPack(int cost, int value, int amount) { if(cost*amount>=nLimit) CompletePack(cost, value); else { int k=1; while(k<amount) { ZeroOnePack(k*cost, k*value); amount-=k; k<<=1; } ZeroOnePack(amount*cost, amount*value); } } int main() { while(scanf("%d",&nKind)!=EOF&&nKind>0) { int sum=0; for(int i=0;i<nKind;i++) { scanf("%d %d",&val[i],&bag[i]); weight[i]=val[i]; sum+=val[i]*bag[i]; } memset(dp,0,sizeof(dp)); nLimit=sum/2; for(int i=0;i<nKind;i++) { MultiplyPack(weight[i],val[i],bag[i]); } printf("%d %d ",sum-dp[nLimit],dp[nLimit]); } return 0; }