思考
首先这道题目我WA了很多次,在没有思路的情况下去偷偷看了一下题解。题解中关键的一步 按照Q-P从小到大排序 让我十分不解,为什么会有这种操作。
而且很多博客,只说为了无后效性之类的,完全没有解释清除(可能大佬们不屑于对这种题目多费口舌)。作为一只小蒟蒻,在翻阅了很多博客与思考之后。
想到:
设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大的先买。这是暴力思考的想法。
但是DP的递推是与暴力顺序完全是相反的举个例子。
3 10
P Q V
5 10 5 物品1
3 5 6 物品2
2 7 3 物品3
Q-P中最大的是 5 10 5,如果暴力算法的话 从物品1(选)->物品3(不选)->物品2 (选) 最大价值11
但是DP的话 就得从 限制最小的 物品2 -> 物品3 -> 物品1 最大价值11
10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
物品1 | 5 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
物品3 | 3 | 3 | 3 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
物品2 | 9 | 6 | 6 | 6 | 6 | 6 | 0 | 0 | 0 | 0 | 0 |
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include <cstdio> #include <cstring> #include <algorithm> int n,m,dp[5500],MAX=0; struct node{ int P,Q,V; }good[550]; bool CMP(node a,node b){ return (a.Q-a.P) < (b.Q-b.P); } int main(){ while( scanf("%d%d",&n,&m) != EOF ){ for(register int i=1;i<=n;i++){ scanf("%d%d%d",&good[i].P,&good[i].Q,&good[i].V); } memset(dp,0,sizeof(dp)); std::sort(good+1,good+1+n,CMP); for(register int i=1;i<=n;i++) for(register int j=m;j>=good[i].Q;j--){ dp[j] = std::max(dp[j],dp[j-good[i].P]+good[i].V); } printf("%d\n",dp[m]); } return 0; }