hdu2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活(多重背包+二进制优化模板)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Flynn_curry/article/details/50659518


http://acm.hdu.edu.cn/showproblem.php?pid=2191

题意:你所拥有的金额为V,物品种类为n,每种价格为cost,重量为weight,数量有限为amount个,求用这些钱(可剩余)可以买到最多多重的粮食?


思路:每种物品数量有限,多重背包。直接用九讲里二进制优化过的模板就行。每种物品拆分为系数为2次幂的物品,对这些物品用以01背包的思想,背包不要求装满。


#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <string.h>
#include <iostream>

using namespace std;

typedef long long LL;

const int N = 1005;
const int INF = 0x3f3f3f3f;

int dp[N], V;

void ZeroOnePack(int cost, int weight)
{
    for(int j = V; j >= cost; j--)
        dp[j] = max(dp[j], dp[j-cost]+weight);
}

void CompletePack(int cost, int weight)
{
    for(int j = cost; j <= V; j++)
        dp[j] = max(dp[j], dp[j-cost]+weight);
}

void MultiplePack(int cost, int weight, int amount)
{
    if(cost*amount>=V)
    {
        CompletePack(cost, weight);
        return;
    }
    int k = 1;
    while(k < amount)
    {
        ZeroOnePack(cost*k, weight*k);
        amount-=k;//注意在前面
        k=k*2;
    }
    ZeroOnePack(amount*cost, amount*weight);
}

int main()
{
   // freopen("in.txt", "r", stdin);
    int t, n;
    int cost[N], weight[N], amount[N];
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d%d", &V, &n);
        for(int i = 1; i <= n; i++)
            scanf("%d%d%d", &cost[i], &weight[i], &amount[i]);
        memset(dp, 0, sizeof(dp));
        for(int i = 1; i <= n; i++)
            MultiplePack(cost[i], weight[i], amount[i]);
      /*  for(int i = 0; i <= V; i++)
            printf("%d ", dp[i]);
        printf("\n");*/
        printf("%d\n", dp[V]);
    }
    return 0;
}


展开阅读全文

没有更多推荐了,返回首页