// [7/24/2014 Sjm] /* 模拟一组测试数据: 2 10 5 10 5 3 5 6 1)若先选择第一组先来: 背包所用容量: 0 1 2 3 4 5 6 7 8 9 10 第一遍循环: 0 0 0 0 0 0 0 0 0 0 5 第二遍循环: 0 0 0 0 0 6 6 6 6 6 6 2)若先选择第二组先来: 背包所用容量: 0 1 2 3 4 5 6 7 8 9 10 第一遍循环: 0 0 0 0 0 6 6 6 6 6 6 第二遍循环: 0 0 0 0 0 6 6 6 6 6 11 可见选择物品的顺序会影响最后的结果。 再看方程: dp[j] = max(dp[j], dp[j - arr[i].p] + arr[i].v) 结合测试数据发现,只有保证 dp[j - arr[i].p] 最优,才能保证 dp[j] 最优,满足无后效性。 若想使 dp[j - arr[i].p] 最优,即要保证: 对于任意两组值:1) p1, q1, v1 和 2) p2, q2, v2 假设先选择1),则若想满足无后效性, 那么 j-arr[2].p >= arr[1].q,且 j-arr[1].p <= arr[2].q (否则可能出现,依赖先选2)计算的值取到更优的解) 由此推得:arr[1].q - arr[1].p <= arr[2].q - arr[2].p,得到如何去决定物品的顺序。。。 当然如果不想这样证明,还有另外一种理解方式: q-p 的差值越小,在每次循环时,与基本的01背包相比,不更新的值也就越少,也就越接近基本的01背包,求出的值也就相对越大。 */
#include <iostream> #include <cstdlib> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int MAX = 505; int N, M; int dp[5005]; struct node { int p, q, v; }; node arr[MAX]; bool Cmp(const node &n1, const node &n2) { return (n1.q - n1.p < n2.q - n2.p); } int Solve() { memset(dp, 0, sizeof(dp)); for (int i = 1; i <= N; ++i) { for (int j = M; j >= arr[i].q; --j) { dp[j] = max(dp[j], dp[j - arr[i].p] + arr[i].v); } } return dp[M]; } int main() { //freopen("input.txt", "r", stdin); while (~scanf("%d %d", &N, &M)) { for (int i = 1; i <= N; ++i) { scanf("%d %d %d", &arr[i].p, &arr[i].q, &arr[i].v); } sort(arr + 1, arr + N + 1, Cmp); printf("%d ", Solve()); } return 0; }