HDOJ1171(多重背包)

#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;
}
原文地址:https://www.cnblogs.com/program-ccc/p/4705067.html