HDU-3446 Proud Merchants(动态规划)

HDU-3446 Proud Merchants

Recently, iSea went to an ancient country. For such a long time, it was the most wealthy and powerful kingdom in the world. As a result, the people in this country are still very proud even if their nation hasn’t been so wealthy any more.
The merchants were the most typical, each of them only sold exactly one item, the price was Pi, but they would refuse to make a trade with you if your money were less than Qi, and iSea evaluated every item a value Vi.
If he had M units of money, what’s the maximum value iSea could get?

Input

There are several test cases in the input.

Each test case begin with two integers N, M (1 ≤ N ≤ 500, 1 ≤ M ≤ 5000), indicating the items’ number and the initial money.
Then N lines follow, each line contains three numbers Pi, Qi and Vi (1 ≤ Pi ≤ Qi ≤ 100, 1 ≤ Vi ≤ 1000), their meaning is in the description.

The input terminates by end of file marker.

Output

For each test case, output one integer, indicating maximum value iSea could get.

Sample Input

2 10
10 15 10
5 10 5
3 10
5 10 5
3 5 6
2 7 3

Sample Output

5
11
先将题目转化为0-1背包问题
我们不妨把大顺序确定下来。
也就是说,比方说A、B、C三样商品,我们不管他买不买,我们只要确定下来如果他买,那肯定先买A再买C,
那接下来是不是就不需要考虑顺序,只需要使用以上的0/1背包算法直接来。
这就是我们的思路,先把顺序给考虑了,在套用以上0/1背包算法。
举例如下

    3 10
    5 5 5 ----A商品
    3 3 6   ----B商品
    2 3 3   ----C商品

其实,就是让C商品的q不等于p,其他都相同,这时,你就会发现如果要买C商品的话,肯定得先买C商品,因为买C商品的代价最大。
所以,我们可以按照qi-pi的顺序来确定大顺序。这里我们还可以用更严谨的方式来证明一下,
比如A:p1 q1, B:p2 q2,然后,假设单独买A或者B的话,都是可以买到的。
这时,若先买A,则你至少需要p1+q2的钱;若先买B,则至少需要p2+q1的钱。那肯定是花最少的钱,所以如果先买A再买B,那么p1+q2<p2+q1,
转换一下,就是q1-p1>q2-p2,也就是说qi-pi大的先买。

这里还得注意一点就是,排序的时候,得按照qi-pi从小到大排序
因为每个物品都有一个限制q,而01背包dp是从前i个物品转移到前i+1个物品,所以必须保证转移时无后效性,即前面i个物品选择的结果不会影响到后面的选择,在这里体现在前i个物品中会影响的范围为q-p;如果第i+1个物品的q-p > 前i个物品的q-p,则可以保证如果选择第i个物品,那么前面i+1个物品的q的限制条件都能满足。 即 qi+1 在的位置>qi。
因为dp过程中,dp[1][n]先将第一件物品考虑完,dp[2][n]在第一件物品的情况下考虑第二件物品,所以第二件物品会更新第一种物品,但第一种物品不会更新第二种物品,相当于先购买第二种物品再购买第一种物品,第二种物品的购买与否会影响第一种物品的购买。

代码:

#include <iostream>
#include<cstdio>
#include <algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
struct thing{
    int w,v,q;
};
struct thing  th[510];
int dp[510][5010];
const int minn=-0x7f7f7f;
int cmp(struct thing a,struct thing b){
    return a.q-a.v<b.q-b.v;
}
int main()
{
    int T;
    int n,c;
    while(scanf("%d %d",&n,&c)!=EOF){
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++){
            scanf("%d %d %d",&th[i].v,&th[i].q,&th[i].w);
        }
        sort(th+1,th+1+n,cmp);
        for(int i=1;i<=n;i++){
            for(int j=0;j<=c;j++){
                if(j>=th[i].v&&j>=th[i].q)
                    dp[i][j]=max(dp[i-1][j],dp[i-1][j-th[i].v]+th[i].w);
                else
                    dp[i][j]=dp[i-1][j];
            }
        }
        printf("%d\n",dp[n][c]);

    }
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值