HDU 3466——Proud Merchants【01揹包 + 排序消除后效性】

题目传送门

与顺序有关的01揹包,先按q-p排序再来处理,难想容易敲。


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


题意:

你有m块钱,有n件商品,每件商品有它的价格p 要买这件商品至少拥有的钱数q和价值w,问能获得的最大价值是多少


分析:

  • 经典的01揹包
  • 商品如果没有属性q的话就是一个单纯的01揹包,正是因为该属性,如果再像01揹包那样求解的话就有了后效性,因为很可能存在这种情况:先买物品1就买不了物品2,但是如果先买物品2就可以继续买物品1.
  • 下面我们来找一下出现这种情况的条件是什么:假设现在又两件物品1和2,你手中有k块钱,而且如果先买1的话能买2,但是先买2的话不能买1,则有:
    p1 + q2 ≤ k < p2 + q1
    移项得,
    q1 - p1 > q2 - p2
    好的,如果两件商品满足q1 - p1 > q2 - p2,那么一定存在一个或多个k值满足 p1 + q2 ≤ k < p2 + q1 ,所以我们在考虑买物品的时候一定要考虑 q减p 的值大的。
    可是如果你按照q-p从大到小排序的话,就又错了。由于01揹包是倒序过程,所以需要将
    (p-q)升序排序

AC代码:

#include <iostream>
#include <vector>
#include <utility>
#include <cstring>
#include <algorithm>
#include <map>
#include <queue>
#include <stack>
#include <cstdio>
#include <fstream>
#include <set>
using namespace std;
typedef long long ll;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

const int MAXN = 5000 + 7;
#define INF 0x3f3f3f


ll dp[MAXN];
struct node {
	int p, q, v;
	bool operator < (const node& t)const {
		return (q - p) < (t.q - t.p);
	}
}node[MAXN];
int main() {

	int n, k;
	while (cin >> n >> k) {
		for (int i = 1; i <= n; i++) {
			cin >> node[i].p >> node[i].q >> node[i].v;
		}
		memset(dp, 0, sizeof dp);
		sort(node + 1, node + n + 1);

		for (int i = 1; i <= n; i++) {
			for (int j = k; j >= node[i].q; j--) {
				dp[j] = max(dp[j], dp[j - node[i].p] + node[i].v);
			}
		}
		cout << dp[k] << endl;
	}

	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章