HDU 3466 - Proud Merchants

题目描述

Proud Merchants

解法:排序+0-1背包问题

先解释怎么处理最低交易价格 Q i Q_i 的问题:

示例1
3 10
5 10 5 (commodity A)
3 5 6 (commodity B)
2 7 3

如果我们先买A商品再买B商品,则总价值为11;如果先买B商品,那么下一次就不可以购买A上品了,故说明最低交易价格主要体现在购买顺序的问题上。

假设有商品A、B,其对应的数据分别为 P a , Q a P_a, Q_a P b , Q b P_b, Q_b ,如果先买A再买 B,那么至少需要 P a + Q b P_a+Q_b 的金钱;如果反过来则至少需要 P b + Q a P_b+Q_a 的金钱。我们再假设此时的购买顺序为先A后B这样花的钱最少,那么有不等式 P a + Q b > P b + Q a P_a+Q_b > P_b+Q_a ,即 P a Q a > P b Q b P_a-Q_a>P_b-Q_b . 那么也就说 P Q P-Q 大的商品应该优先购买,于是我们就按照 P Q P-Q 的值先对商品进行一个排序。

接着我们思考一个问题: P Q P-Q 大的商品先购买,那么排序应该是按照 P Q P-Q 的值从小到大,还是从大到小呢?在0-1背包问题中,是倒序枚举,故排序时应该按照从小到大的顺序,这样就保证了 P Q P-Q 大的商品先购买

最后,在 j j 的循环里面,我们应该将 j > = v o l u m e [ i ] j>=volume[i] 改为 j = c o m [ i ] . Q j=com[i].Q ,因为这样既满足了最低交易价格也满足有充足的的金钱买下物品

#include <iostream>
#include <algorithm>

using namespace std;

struct commodity{
    int p, q, v;
};

bool cmp(commodity a, commodity b)
{
    return a.q-a.p<b.q-b.p;
}

int main()
{
    int n, m;
    while(~scanf("%d%d", &n, &m))
    {
        commodity com[505] = {0};
        int dp[5005] = {0};
        for(int i=1;i<=n;i++)
            scanf("%d%d%d", &com[i].p, &com[i].q, &com[i].v);
        sort(com, com+n, cmp);
        for(int i=1;i<=n;i++)
            for(int j=m;j>=com[i].q;j--)
                dp[j] = max(dp[j], dp[j-com[i].p]+com[i].v);
        printf("%d\n", dp[m]);
    }
    return 0;
}
发布了152 篇原创文章 · 获赞 22 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_38204302/article/details/105201166