HDU - 2191 珍惜現在,感恩生活(多重揹包板題)

sunlanchang發表於2019-01-31

Description

現在假設你一共有資金n元,而市場有m種大米,每種大米都是袋裝產品,其價格不等,並且只能整袋購買。
請問:你用有限的資金最多能採購多少公斤糧食呢?

Input

輸入資料首先包含一個正整數C,表示有C組測試用例,每組測試用例的第一行是兩個整數n和m(1<=n<=100, 1<=m<=100),分別表示經費的金額和大米的種類,然後是m行資料,每行包含3個數p,h和c(1<=p<=20,1<=h<=200,1<=c<=20),分別表示每袋的價格、每袋的重量以及對應種類大米的袋數。

Output

對於每組測試資料,請輸出能夠購買大米的最多重量,你可以假設經費買不光所有的大米,並且經費你可以不用完。每個例項的輸出佔一行。

Sample Input

1
8 2
2 100 4
4 100 2

Sample Output

400

Solution

多重揹包板題,包含了01揹包、完全揹包。注意:

  • dp[]的初始化
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 111, INF = 0x3f3f3f3f;
int dp[maxn];
int total_cost, total_kind;
struct Rice
{
    int weight, cost, num;
};
Rice arr[maxn];
void zero_pack(int cost, int weight)
{
    for (int i = total_cost; i - cost >= 0; i--)
        dp[i] = max(dp[i], dp[i - cost] + weight);
}
void complete_pack(int cost, int weight)
{
    for (int i = cost; i <= total_cost; i++)
        dp[i] = max(dp[i], dp[i - cost] + weight);
}
void multiple_pack(int cost, int weight, int num)
{
    //如果大於等於金額,就按完全揹包處理(此時相當於不限定袋數)
    if (cost * num >= total_cost)
    {
        complete_pack(cost, weight);
        return;
    }
    //打包成1 2 4 8 ...份
    int k = 1;
    while (k < num)
    {
        zero_pack(k * cost, k * weight);
        num -= k;
        k << 1;
    }
    //處理剩下的物品
    zero_pack(num * cost, num * weight);
}
int main()
{
    // freopen("in.txt", "r", stdin);
    int T;
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d%d", &total_cost, &total_kind);
        for (int i = 1; i <= total_kind; i++)
            scanf("%d%d%d", &arr[i].cost, &arr[i].weight, &arr[i].num);
        // 多重揹包
        memset(dp, 0, sizeof(dp));
        dp[0] = 0;
        for (int i = 1; i <= total_kind; i++)
            multiple_pack(arr[i].cost, arr[i].weight, arr[i].num);
        printf("%d\n", dp[total_cost]);
    }
    return 0;
}

相關文章