P1064 金明的预算方案 (01背包)

P1064 金明的预算方案 (01背包)

题目连接
题目大意:在01背包问题上的一个小小变形,每个物品分为主件和附件,要买附件必须拥有它的主件,每次主件最多拥有2个附件。
样例:
1000(你有的钱) 5(物品的数量)
n个物品
物品的单价 物品的价值 物品是不是附件 0是主件 非0 是几就是第几个物品的附件
800 2 0
400 5 1
300 5 1
400 3 0
500 2 0
输出 2200
求不超过总钱数的物品的价格与价值乘积的总和的最大值

感觉题解写的超棒!
copy一下:
带有附件的背包问题,它属于01背包的变式。

这题还好,每一个物品最多只有两个附件,那么我们在对主件进行背包的时候,决策就不再是两个了,而是五个。

还记得01背包的决策是什么吗?

1.不选,然后去考虑下一个

2.选,背包容量减掉那个重量,总值加上那个价值。

这个题的决策是五个,分别是:

1.不选,然后去考虑下一个

2.选且只选这个主件

3.选这个主件,并且选附件1

4.选这个主件,并且选附件2

5.选这个主件,并且选附件1和附件2.
然后就很好写了

#include <bits/stdc++.h>
using namespace std;

const int maxn = 30000 + 10;
int dp[maxn], price[maxn], value[maxn], is[maxn];

struct node {
   int price, value;
};

vector<node> data[maxn];

int main()
{
    int n, m;
    scanf("%d %d", &n, &m);
    for(int i = 0; i < m; i++)
    {
        int u, v, p;
        scanf("%d %d %d", &p, &v, &u);
        if(!u) data[i].push_back((node) {p, v});
        else data[u - 1].push_back((node) {p, v});
    }

    for(int i = 0; i < m; i++)
    {
        if(data[i].size() == 0) continue;
        for(int j = n; j >= data[i][0].price; j--)
        {
            dp[j] = max(dp[j], dp[j - data[i][0].price] + data[i][0].price * data[i][0].value);
            if(data[i].size() >= 2)
            {
                if(j >= data[i][0].price + data[i][1].price)
                dp[j] = max(dp[j], dp[j - data[i][0].price - data[i][1].price] + data[i][0].price * data[i][0].value + data[i][1].price * data[i][1].value);
            }
            if(data[i].size() == 3)
            {
                if(j >= data[i][0].price + data[i][2].price) 
                dp[j] = max(dp[j], dp[j - data[i][0].price - data[i][2].price] + data[i][0].price * data[i][0].value + data[i][2].price * data[i][2].value);
                if(j >= data[i][0].price + data[i][2].price + data[i][1].price)
                dp[j] = max(dp[j], dp[j - data[i][0].price - data[i][1].price - data[i][2].price] + data[i][0].price * data[i][0].value + data[i][1].price * data[i][1].value + data[i][2].price * data[i][2].value);
            }

        }
    }
    printf("%d\n", dp[n]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值