Time Limit: 1000MS | Memory Limit: 65536KB | 64bit IO Format: %I64d & %I64u |
Description
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
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
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
Source
每件物品有一个限制,只有当你当前现金大于qi的时候才会卖给你。
这题好好想了一下,跟之前做过的一道题有些类似。考虑简化版,有两个物品(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题要注意后效性是否存在,如果存在通过改变顺序之类的办法来取消后效性。再有杭电上饭卡那题,qi恒定为5,所以也是需要排序的。
ac代码:#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
struct node
{
int p,q,v;
} a[555];
int cmp(node x,node y)//按q-p排序,保证差额最小为最优
{
return x.q-x.p<y.q-y.p;
}
int main()
{
int n,m,i,j;
int dp[5555];
while(~scanf("%d%d",&n,&m))
{
for(i = 0; i<n; i++)
scanf("%d%d%d",&a[i].p,&a[i].q,&a[i].v);
memset(dp,0,sizeof(dp));
sort(a,a+n,cmp);
for(i = 0; i<n; i++)
{
for(j = m; j>=a[i].q; j--)//剩余的钱大于q才能买
{
dp[j] = max(dp[j],dp[j-a[i].p]+a[i].v);//这里的j-a[i].p决定了之前的排序方法
}
}
printf("%d\n",dp[m]);
}
return 0;
}