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.
其实就是dp后效性的问题,除了i和v这2个维度还多了一个维度q,直接套用公式无法去除后效性,
先找到选择顺序的规律,去除后效性,再使用01背包;
选取的规律: 比如A:p1 q1, B:p2 q2,然后,假设单独买A或者B的话,都是可以买到的。
这时,若先买A,则你至少需要p1+q2的钱;若先买B,则至少需要p2+q1的钱。那肯定是花最少的钱咯,所以如果先买A再买B,那么p1+q2<p2+q1,
转换一下,就是q1-p1>q2-p2,也就是说qi-pi大的先买。
这里还得注意一点就是,排序的时候,得按照qi-pi从小到大排序,
因为你买第n件商品的时候,是在比较你是否要先买第n件商品。
打个比方让大家更好地理解,比如说f(3, 10),是不是max(f(2, 10-p3)+v3, f(2, 10)),
你会发现这个第一种情况f(2,10-p3)+v3中,是先买了第三件商品,也就是说排在后面的商品会先买。(重点)
还有一个要注意的:我们背包问题写的状态转移方程是从后往前选的(一维);
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; struct GOOD{
int c, q, w;
}g[]; bool cmp(GOOD x, GOOD y){
return x.q-x.c<y.q-y.c;
} int main()
{
int n, V, f[];
while(cin>>n>>V)
{
memset(f, , sizeof(f));
for(int i=; i<=n; i++)
cin>>g[i].c>>g[i].q>>g[i].w;
sort(g+, g+n+, cmp); for(int i=; i<=n; i++)
for(int v=V; v>=g[i].q; v--)
f[v]=max(f[v], f[v-g[i].c]+g[i].w);
cout<<f[V]<<endl;
}
return ;
}