题目描述
解法:排序+0-1背包问题
先解释怎么处理最低交易价格 Q i Q_i Qi 的问题:
示例1
3 10
5 10 5 (commodity A)
3 5 6 (commodity B)
2 7 3
如果我们先买 A A A 商品再买 B B B 商品,则总价值为 11 11 11;如果先买 B B B 商品,那么下一次就不可以购买 A A A 商品了,故说明最低交易价格主要体现在购买顺序的问题上
假设有商品 A 、 B A、B A、B,其对应的数据分别为 P a 、 Q a P_a、 Q_a Pa、Qa 和 P b 、 Q b P_b、Q_b Pb、Qb,如果先买 A A A 再买 B B B,那么至少需要 P a + Q b P_a+Q_b Pa+Qb 的金钱;如果反过来则至少需要 P b + Q a P_b+Q_a Pb+Qa 的金钱
我们再假设此时的购买顺序为先 A A A 后 B B B 这样花的钱最少,那么有不等式 P a + Q b > P b + Q a P_a+Q_b > P_b+Q_a Pa+Qb>Pb+Qa,即 P a − Q a > P b − Q b P_a-Q_a>P_b-Q_b Pa−Qa>Pb−Qb
那么也就说 P − Q P-Q P−Q 大的商品应该优先购买,于是我们就按照 P − Q P-Q P−Q 的值先对商品进行一个排序
接着我们思考一个问题: P − Q P-Q P−Q 大的商品先购买,那么排序应该是按照 P − Q P-Q P−Q 的值从小到大,还是从大到小呢?
在 0-1 背包问题中,是倒序枚举,故排序时应该按照从小到大的顺序,这样就保证了 P − Q P-Q P−Q 大的商品先购买
最后,在 j j j的循环里面,我们应该将 j > = v o l u m e [ i ] j>=volume[i] j>=volume[i] 改为 j > = c o m [ i ] . Q j>=com[i].Q j>=com[i].Q,因为这样既满足了最低交易价格也满足有充足的的金钱买下物品
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
struct commodity{
int p, q, v;
};
bool cmp(commodity a, commodity b){return a.q-a.p<b.q-b.p;}
int main()
{
int n, m;
while(~scanf("%d%d", &n, &m))
{
commodity c[505] = {0};
vector<int> dp(5005, 0);
for(int i=1;i<=n;i++)
scanf("%d%d%d", &c[i].p, &c[i].q, &c[i].v);
sort(c, c+n, cmp);
for(int i=1;i<=n;i++)
for(int j=m;j>=c[i].q;j--)
dp[j] = max(dp[j], dp[j-c[i].p]+c[i].v);
printf("%d\n", dp[m]);
}
return 0;
}