您的位置:首页 > 其它

HDU 3466 Proud Merchants(背包)

2016-08-02 13:00 309 查看
题目:

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


这个题目很接近0-1背包问题,有一个地方不同就是,需要q的容量才能装入p大小的东西。

这个差异,我们需要在2个地方进行修改。

第一,刷表的2层for循环,内层循环要以q为界而不是以p为界。

老实说,刚开始我以为只要改这个地方就行了,结果对于题目中给的输入样例

3 10
5 10 5
3 5 6
2 7 3

都算不对。

然后我想了一下,因为0-1背包的刷表的方法是先选后面的物品,再选前面的物品。

虽然对于0-1背包问题,随便什么顺序都是一样的,

但是这个问题里面,先选3 5 6之后,就没法选5 10 5了。

如果先选5 10 5,然后是可以选3 5 6的。

然后顺序问题要怎么样解决呢?

肯定不是对顺序进行枚举!毕竟有500个物品。

这个题目的顺序问题还是不难的,就是计算每个物品的q-p的值,然后以此为序来排序即可。

如果2个物品的q-p是一样的,我们甚至不关心这2个物品的顺序!

具体的原理我也说不太清楚,反正就感觉很显然。

简单的说,装完 i 之后能不能装 j 取决于背包有没有 pi+qj ,装完 j 之后能不能装 i 取决于背包有没有pj+qi

因为2种顺序的总价值是一样的,所以我们应该选择pi+qj和pj+qi里面较小的那个数(对应的那个顺序)。

这也就是先选择q-p较大的物品装入背包的意思。

因为刷表是从后面的物品先装入的,所以物品要按照q-p升序排序。

对于如何寻找出q-p这样的贪心策略,可以看看类似的一个题目
点击打开我的博客

代码:

#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;

int n, m;
struct node
{
int p;
int q;
int v;
};

node nod[501];
int r[5001];

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

int main()
{
while (cin >> n >> m)
{
for (int i = 1; i <= n; i++)cin >> nod[i].p >> nod[i].q >> nod[i].v;
sort(nod + 1, nod + n, cmp);
memset(r, 0, sizeof(r));
for (int i = 1; i <= n; i++)for (int j = m; j >= nod[i].q; j--)if (r[j] < r[j - nod[i].p] + nod[i].v)r[j] = r[j - nod[i].p] + nod[i].v;
cout << r[m] << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: