Description
Input
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
一开始没看清题意,以为是Q必须不大于M才能买,所以输入数据时直接过滤掉Q>M的数
测试的时候发现第二个数据错了,检查的时候才发现每买一件,M的值都会减少,不能只过滤掉Q>M的数然后直接dp
因为它有购买顺序问题
先来看看dp公式:
dp[k] = max(dp[k], dp[k - num[i].p] + num[i].v);是从后面往前面找的,也就是后面的数选上了就是确定的,那么如果选了后面的数之后剩下的M变得很小,则接下来的商品能买的就变得很少,即使本来的钱是可以买这两件商品的,但现在变成只能买后面一件
举个例子:就用题目给的数据的第二个例子来说:
M=10
num[1].p = 5 num[1].q = 10 num[1].v = 5num[2].p = 3 num[2].q = 5num[2].v = 6
num[3].p = 2 num[3].q = 7num[3].v = 3
如果按照这样的顺序,因为dp从后面开始
所以先买了num[3],之后M就剩下8
接下来再买了num[2], M就剩下5不够买num[1],次是价值为9
那我一开始不买num[3],先买num[2],M就剩下7,因为dp原因,它不会回去买num[3],只能向前买num[1],但是num[1]需要的Q>M,所以买不了,价值为6
由此可见,按这样的顺序能买到的最大价值为9
那如果颠倒过来,
M=10
num[1].p = 2 num[1].q = 7 num[1].v = 3num[2].p = 3 num[2].q = 5num[2].v = 6
num[3].p = 5 num[3].q = 10num[3].v = 5
按上面那思路可以得出能买到的最大价值为11
再细看一下,不难得出,假使A为 p=3, q=5, v=6 B为p=5, q=10, v=5
如果先买A再买B,则需要pa+qb=13
如果先买B再买A,则需要pb+qa=10
我们肯定要选后者
那么就得出了商品排序要满足:pa+qb>pb+qa
交换位置得出:qa-pa<qb-pb
以下是AC代码:
#include<iostream> #include<string.h> #include<algorithm> using namespace std; int dp[5005]; struct M { int p, q, v; }num[505]; bool cmp(M a, M b) { return a.q - a.p < b.q - b.p; } int main() { int n, m; while (cin >> n >> m) { int j = 0; memset(dp, 0, sizeof(dp)); for (int i = 0; i < n; ++i) { cin >> num[i].p >> num[i].q >> num[i].v; if (num[i].q > m) { i--; n--; } } sort(num, num + n, cmp); for (int i = 0; i < n; ++i) { for (int k = m; k >=num[i].q; --k) { dp[k] = max(dp[k], dp[k - num[i].p] + num[i].v); } } cout << dp[m] << endl; } return 0; }