HDU 3466 Pround Merchants

本文介绍了一种解决背包问题的巧妙方法,通过引入额外参数并根据价格与价值的差值进行排序,避免了传统方法中可能遇到的问题,确保了算法的正确性和效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:传送门
题面:

Proud Merchants
Problem Description

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

题目大意:

输入有多组数据。现在有 n n n个物品 V V V元钱,每个物品有三个参数,分别是价格 w i w_i wi,买这个物品至少拥有的钱数 p i p_i pi,价值 v i v_i vi。你要用 V V V元钱买到价值尽量高的物品。

这题就比较巧妙了
多了一个参数
其实正解很简单
根据 p i − v i p_i-v_i pivi从小到大排序就好了
那为什么是这样的呢?
假设如果一个物品是 5 5 5 6 6 6
一个物品是 5 5 5 3 3 3
对第一个进行背包的时候只有 f [ 6 ] , f [ 7 ] , … , f [ m ] f[6],f[7],…,f[m] f[6],f[7],,f[m]
再对第二个进行背包的时候
会借用前面的 f [ 5 ] , f [ 4 ] f[5],f[4] f[5],f[4] f [ 1 ] f[1] f[1]
但是现在这些值都是0
会导致结果出错
于是要想到只有后面要用的值前面都可以得到
那样才不会出错
A : v 1 , p 1 A:v_1,p_1 A:v1,p1 B : v 2 , p 2 B:v_2,p_2 B:v2,p2
如果先 A A A B B B
则至少需要 v 1 + p 2 v_1+p_2 v1+p2的容量
如果先 B B B A A A
至少需要 v 2 + p 1 v_2+p_1 v2+p1的容量
那么就是 v 1 + p 2 > v 2 + p 1 v_1+p_2 >v_2+p_1 v1+p2>v2+p1
变形之后就是 p 1 − v 1 &lt; p 2 − v 2 p_1-v_1&lt;p_2-v_2 p1v1<p2v2
所以要针对每个属性的 p − v p-v pv来进行排序

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <complex>
#include <algorithm>
#include <climits>
#include <queue>
#include <map>
#include <vector>
#include <iomanip>
#define A 1000010
#define B 2010
#define ll long long

using namespace std;
struct node {
    int w, v, p;
    friend bool operator < (const node a, const node b) {
        return a.p - a.w < b.p - b.w;
    }
} e[A];
int T, n, V, f[A];

int main() {
    while (cin >> n >> V) {
        memset(f, 0, sizeof f);
        for (int i = 1; i <= n; i++) cin >> e[i].w >> e[i].p >> e[i].v;
        sort (e + 1, e + n + 1);
        for (int i = 1; i <= n; i++)
          for (int j = V; j >= e[i].p; j--)
            f[j] = max(f[j], f[j - e[i].w] + e[i].v);
        cout << f[V] << endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

良月澪二

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

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

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

打赏作者

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

抵扣说明:

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

余额充值