您的位置:首页 > 其它

hdu 3466 Proud Merchants <背包+sort排序>

2015-08-27 12:54 337 查看

Proud Merchants

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)

Total Submission(s): 3616 Accepted Submission(s): 1511



[align=left]Problem Description[/align]
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?

[align=left]Input[/align]
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.

[align=left]Output[/align]
For each test case, output one integer, indicating maximum value iSea could get.

[align=left]Sample Input[/align]

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


[align=left]Sample Output[/align]

5
11


[align=left]Author[/align]
iSea @ WHU

题意:

首先输入n,m两个数;n代表物品的个数,m代表总共的钱数;接下来输入n行,每行3个数,第一个数是商品的标价,第二个数是卖家要求你手里面最少有的钱数才能购买人家的商品,第3个数是你认为这个商品的价值是多少;最终让你求用你手里面的m元钱购买商品使你手里面所得到(你认为的)价值最大!

思路:

这道题和一般的01背包不一样,因为一般的01背包与装物品的顺序无关,所以我们就能直接01背包去做,而这道题因为涉及到要买某个东西,首先手里面要有多少的钱的限制,有时候虽然你的钱能够买这两个物品,但是就是因为你购买的顺序不对,所以造成你只能购买一件,另一件不能购买!

例如:A:p1=5, q1=10, v1=5;

B:p2=3, q2=5, v2=6;

如果你手里面有10块钱,你先购买A再购买B,你会买到价值为11元的东西,如果你先买B的话你就只能购买一件商品了,所以这道题不能用01背包直接做!

怎样我们才能更好的控制一下,如果A,B两个商品都买的话就只能先买A再买B呢?怎样才能按照这样的顺序进行购买商品,使买到的商品的价值最大呢?首先我们先就上面这个例子进行分析看看只有满足怎样的购买顺序才能使能购买的商品不因为顺序的原因而被迫不买!

仍然以上面的这个例子为例进行分析:如果先买物品A再买物品B的话我至少需要10元钱,如果先买物品B再买物品A的话,我们至少需要13元钱,也就是得到相同的价值的物品,我们却需要两个不同价值的钱,当然我们选择要花少的钱购买相同价值的商品了!这两个价值满足p1+q2<p2+q1(为了使数据满足一定的顺序进行购买,因此我们使所有的数据都按照(q1-p1>q2-p2)这样的顺序排序,这样购买最终我们所需的钱数就是最少的,也就是拿同样多的钱,我们可以买更大价值的东西!在这里p1+q2<p2+q1与q1-p1>q2-p2等价,只不过在这里我们将描述同一个物体的变量放到不等式的一边(q1-p1>q2-p2),然后再进行排序操作比较方便罢了),如果我们都按照这样的顺序(qi-pi从大到小的顺序)进行排序,

先买差值大的物品再买差值小的物品,也就是要是买的话肯定是按照先A后B的顺序,这样我们就不会因为顺序的原因而少买东西!然后我们再根据01背包将能够购买的最大的价值的物品全部购买,就得到我们要求的最大的价值了!
但是,我们还有以点没有考虑,那就是我们知道先选大的差值(qi-pi)去买,那么01背包是怎么操作呢?(bag[j]=max(bag[j],bag[j-cos[i]]+val[i]))
其实01背包的购买都是按照从后向前的顺序进行购买的,也就是说,它的每次的最后一个商品是确定购买的,然后再加上前面的除下用的最后一个的钱之后能够够购买的最大的价值与不购买这个物品进行比较,哪个大就选哪个!(在这个过程中因为是先确定后面的物品是否购买,所以我们要将差值(qi-pi)大的放到后面,差值小的放到前面,也就是前面说的按照从大到小的顺序是进行购买的顺序,而真正排序,然后按照背包执行程序的时候是按照从小到大的顺序!)
总之,就是按照差值(qi-pi)从小到大排序,然后用01背包的方法进行操作就行了!

AC代码:

//艰难的做了一道题,排序真难理解!
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define max(a,b) (a>b?a:b)
using namespace std;
struct inin
{
int p;
int q;
int v;
}a[550];
int bag[5005];
int cmp(inin a,inin b)//这一点一定要记住排序!
{
return (a.q-a.p)<(b.q-b.p);
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(bag,0,sizeof(bag));
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&a[i].p,&a[i].q,&a[i].v);
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)
{
for(int j=m;j>=a[i].q;j--)
{
bag[j]=max(bag[j],bag[j-a[i].p]+a[i].v);
}
}
printf("%d\n",bag[m]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: