Proud Merchants
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 2183 Accepted Submission(s): 869
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?
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.
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
题目大意:
物品价格pi,标度qi;价值vi;
有m的钱;只有m>=qi时 才能买这个物品;
思路:
首先看一下暴力解决,很显然我们可以用枚举的方法,对每个物品都有选与不选两种决策。但即使暴力也存在一个问题,比如对 3 5 6,5 10 5这两个物品,如果我们的决策是两个都不选或者是只选其中一个,显然没什么问题,但如果我们要是两个都选的话,按照之前这个顺序有m>=13(放第一个,先需要M>=5,真正花费为3;再放第二个M》=10才行,所以m>=13),但如果把两个的顺序
交换
一下则m>=10即可,从这里就可以看出问题的所在了。
于是,对任意两个物品i,j,为了避免上面存在的那种问题,我们可以算出两种顺序所需要的最少金额,若先放i再放j,则至少需要Pi+Qj,若是j在前 则至少需要Pj+Qi.如果已知结果是i在前较优的话,则有Pi+Qj<Pj+Qi,即Qi-Pi>Qj-Pj. 所以说Qi-Pi越大 对于暴力求解越优。
0-1背包求解
考虑简化版,有两个物品(p1,q1,v1),(p2,q2,v2),然后物品1先放的话,物品2就可以借助物品1产生的各种状态来进行下一步转移,而如果物品2的q2值过高,在这个[q2,m]的区间内都不存在物品1造成的新状态的话,那么物品1的状态就没有得到利用。而如果交换顺序,先放了物品2,那么显然物品1就可以利用物品2产生的新状态。
所以物品1能从物品2转移的状态区间其实是[min(q1+p2,m),m],物品2能从物品1转移的状态区间是[min(q2+p1,m),m]。所以尽可能地复用这个区间,让区间小的先来,区间大的后来,这样排序之后所有物品都能从前面的物品得到新状态进行转移。
而普通的01背包之所以不需要排序,是因为p1==q1,p2==q2,排序跟不排是一回事。这一类的dp题要注意后效性是否存在,如果存在通过改变顺序之类的办法来取消后效性。
暴力是按照Q-P从大到小先排好序,但由于dp与暴力其实正好是两个逆过程,所以dp前我们是按照Q-P从小到大的顺序排好序。
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
struct goods
{
int P;
int Q;
int v;
}a[505];
bool cmp(goods a,goods b)
{
if(a.Q-a.P<b.Q-b.P)
return true;
else
return false;
}
int dp[5005];
int main()
{
int n,c;
while(cin>>n>>c)
{
memset(dp,0,sizeof(dp));
int i,j;
for(i=1;i<=n;++i)
cin>>a[i].P>>a[i].Q>>a[i].v;
sort(a+1,a+n+1,cmp);
for(i=1;i<=n;++i)
for(j=c;j>=a[i].Q;--j)
{
dp[j]=max(dp[j-a[i].P]+a[i].v,dp[j]);
}
cout<<dp[c]<<endl;
}
}