多重背包(动态规划)

                                   题目B      剁手党                               限时:2000ms

剁手党们整天游荡在各种大小商场,有N种物品,每种物品的数量为C1,C2......Cn。从中任选若干件放在容量为W的背包里,每种物品的体积为W1,W2......Wn(Wi为整数),与之相对应的价值为P1,P2......Pn(Pi为整数)。求背包能够容纳的最大价值。

 

输入

第1行,2个整数,N和W中间用空格隔开。N为物品的种类,W为背包的容量。(1 <= N <= 100,1 <= W <= 50000)

第2 - N + 1行,每行3个整数,Wi,Pi和Ci分别是物品体积、价值和数量。(1 <= Wi, Pi <= 10000, 1 <= Ci <= 200)

 

输出

每组数据输出一行,即可以容纳的最大价值。

 

 

样例输入

样例输出

3 6

2 2 5

3 3 8

1 4 1

 

9

直观的多重背包

 

#include
#include
#include
#include

using namespace std;

const int MAXN = 100 + 10;
int pri[MAXN], wei[MAXN], num[MAXN];
int dp[50010], sum, n;
void zeroOnePack(int price, int weight, int sum)    ///01背包
{
    for (int i = sum; i >= price; i--)
        dp[i] = max(dp[i], dp[i - price] + weight);
}
void completePack(int price, int weight, int sum)   ///完全背包
{
    for (int i = price; i <= sum; i++)
        dp[i] = max(dp[i], dp[i - price] + weight);
}
void multiPack(int n, int sum)          ///多重背包
{
    memset(dp, 0, sizeof(dp));
    for (int i = 1; i <= n; i++)
    {
        if (pri[i] * num[i] > sum)      ///只买第i种大米可以将经费花完
            completePack(pri[i], wei[i], sum);  ///转化为完全背包等价于无限个可取
        else
        {
            for (int k = 1; k < num[i]; k *= 2) ///转化为01背包,系数为1,2,4...2^(k-1)
            {
                zeroOnePack(k * pri[i], k * wei[i], sum);
                num[i] -= k;
            }
            if (num[i] != 0)    ///最后剩余的袋数(num[i]-2^k+1)
                zeroOnePack(num[i] * pri[i], num[i] * wei[i], sum);
        }
    }
    printf("%d\n", dp[sum]);
}
void solve()
{
    while(~scanf("%d%d", &n, &sum))
    {
        for (int i = 1; i <= n; i++)
            scanf("%d%d%d", &pri[i], &wei[i], &num[i]);
        multiPack(n, sum);
    }
}
int main()
{
    solve();
    return 0;
}


 

你可能感兴趣的:(动态规划)