HDU 3466 Proud Merchants ……(01背包 + 排序(物品的选择有先后顺序))

这道题和01背包很类似,唯一不同的就是买每件物品时多了一个限制条件,pQv,需要钱数大于Q才能买,所以买东西需要有先后顺序。以前的01背包不用排序,
dp[j] = max(dp[j],dp[j-w[i]]+v[i])表达的是这第i个物品要不要买,但同时也在判断第i个物品要不要先买,如果先买剩下的空间随便放,看是否得到的价值会更大。
A物品  p1,q1,v1;
B物品  p2,q2,v2
	若先买A,至少需要p1+q2 (p1 == q1情况下)若先买B,至少需要p2+q1;
	A<B,应先买A,即 q1-p1 > q2-p2;即差值大的先买,所以先买的应排到后面
打个比方让大家更好地理解,比如说f(3, 10),是不是max(f(2, 10-p3)+v3, f(2, 10)),你会发现这个第一种情况f(2,10-p3)+v3中,是先买了第三件商品,也就是说排在后面的商品会先买。好的,排好序之后,就把问题就转换为不需要考虑顺序的问题了,那就是上面我们已经解决0/1背包问题了。这样,问题圆满解决了。
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

struct node
{
    int p,q,v;
} num[555];

int cmp(node x,node y)//按q-p排序,保证差额最小为最优
{
    return x.q-x.p<y.q-y.p;
}

int main()
{
    int n, m, i, j, dp[5005];
    while(~scanf("%d%d",&n, &m))
    {
        for(i = 0; i<n; i++)
            scanf("%d%d%d",&num[i].p, &num[i].q, &num[i].v);
        memset(dp, 0, sizeof(dp));

        sort(num, num+n, cmp);

        for(i = 0; i<n; i++)
            for(j = m; j>=num[i].q; j--)//剩余的钱大于q才能买
                dp[j] = max(dp[j], dp[j-num[i].p]+num[i].v);//这里的j-a[i].p决定了之前的排序方法

        printf("%d\n", dp[m]);
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hhjian6666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值