题目:
Proud Merchants
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 6166 Accepted Submission(s): 2549
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?
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.
2 10 10 15 10 5 10 5 3 10 5 10 5 3 5 6 2 7 3
5 11
先说一下题意,有n个物品,你拥有的总钱数是m.你要买东西,接下来n组数据每组数据有三个数p代表这个物品的价格,q代表如果你的钱数少于q你就不能买这个东西,v代表这一件物品的价值,问的是你最多能得到多少价值的物品。
我们的做法是先对每个物品的(q-p)从小到大排序,然后按照01背包的方式来做。
因为q一定大于p,所以不用担心q-p的值会小于0.而问题来了,为什么要对q-p进行排序呢。
我们用一组样例来分析一下。
2 10
5 8 5
2 7 3
如果我们先买A物品,花费5元还剩五元,但是剩余的钱是5元不够7元,所以我们得到的最大价值,只能是5.
但是如果先买B物品的话,先花费2元,剩余8元,然后再买第一件物品,最后可以得到的最大价值是5+3=8.
用p1,q1,p2,q2来表示这两组数据的话,你要买这两个物品的话,如果先买第2个那么你要有的钱数是p2+q1或者p1+q2.很明显,在这里p1+q2>p2+q1,把它们进行移项得到:
q2-p2>q1-p1,所以我们得到的策略是,先选q-p的值比较大的,也就是从大到小排列,但是按照01背包做的话,01背包的本质是先总后面往前取,所以我们按照q-p从小到大排序的话,01背包从后面往前取,正好符合我们从大到小取得思想,所以我们要先排序,后按照01背包做
比赛的时候,感觉这是贪心,又像01背包,但是都没做出来,还是看了大牛的思想才会的。。
参考博客:http://blog.csdn.net/oceanlight/article/details/7866759
代码:
#include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
#define N 500+20
#define M 1000000+10
#define LL long long
using namespace std;
int n,m,dp[50000];
struct node
{
int p;//价格
int q;//钱数小于q就不能买
int v;//价值
} g[N];
bool cmp(node x,node y)
{
return (x.q-x.p)<(y.q-y.p);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
mem(dp,0);
for(int i=0; i<n; i++)
scanf("%d%d%d",&g[i].p,&g[i].q,&g[i].v);
sort(g,g+n,cmp);
for(int i=0; i<n; i++)
{
for(int j=m; j>=g[i].q; j--)
{
dp[j]=max(dp[j],dp[j-g[i].p]+g[i].v);
}
}
printf("%d\n",dp[m]);
}
return 0;
}