这道题和01背包很类似,唯一不同的就是买每件物品时多了一个限制条件,p,Q,v,需要钱数大于Q才能买,所以买东西需要有先后顺序。以前的01背包不用排序,
dp[j] = max(dp[j],dp[j-w[i]]+v[i])表达的是这第i个物品要不要买,但同时也在判断第i个物品要不要先买,如果先买剩下的空间随便放,看是否得到的价值会更大。
A物品 p1,q1,v1;
B物品 p2,q2,v2
若先买A,至少需要p1+q2 (p1 == q1情况下)若先买B,至少需要p2+q1;
若A<B,应先买A,即 q1-p1 > q2-p2;即差值大的先买,所以先买的应排到后面
打个比方让大家更好地理解,比如说f(3, 10),是不是max(f(2, 10-p3)+v3, f(2, 10)),你会发现这个第一种情况f(2,10-p3)+v3中,是先买了第三件商品,也就是说排在后面的商品会先买。好的,排好序之后,就把问题就转换为不需要考虑顺序的问题了,那就是上面我们已经解决0/1背包问题了。这样,问题圆满解决了。
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
struct node
{
int p,q,v;
} num[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, dp[5005];
while(~scanf("%d%d",&n, &m))
{
for(i = 0; i<n; i++)
scanf("%d%d%d",&num[i].p, &num[i].q, &num[i].v);
memset(dp, 0, sizeof(dp));
sort(num, num+n, cmp);
for(i = 0; i<n; i++)
for(j = m; j>=num[i].q; j--)//剩余的钱大于q才能买
dp[j] = max(dp[j], dp[j-num[i].p]+num[i].v);//这里的j-a[i].p决定了之前的排序方法
printf("%d\n", dp[m]);
}
return 0;
}