hdu 3466 Proud Merchants (排序的dp)
2015-08-04 15:41
281 查看
hdu 3466 Proud Merchants
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 3417 Accepted Submission(s): 1410Problem DescriptionRecently, iSea went to an ancient country. For such a long time, it was the most wealthy and powerful kingdom in the world. As a result, the people in this country are still very proud even if their nation hasn’t been so wealthy any more.The merchants were the most typical, each of them only sold exactly one item, the price was Pi, but they would refuse to make a trade with you if your money were less than Qi, and iSea evaluated every item a value Vi.If he had M units of money, what’s the maximum value iSea could get?InputThere are several test cases in the input.Each test case begin with two integers N, M (1 ≤ N ≤ 500, 1 ≤ M ≤ 5000), indicating the items’ number and the initial money.Then N lines follow, each line contains three numbers Pi, Qi and Vi (1 ≤ Pi ≤ Qi ≤ 100, 1 ≤ Vi ≤ 1000), their meaning is in the description.The input terminates by end of file marker.OutputFor each test case, output one integer, indicating maximum value iSea could get.Sample Input2 1010 15 105 10 53 105 10 53 5 62 7 3Sample Output
511这道题目大意是,有n件商品,每件商品的价格是pi,每件商品只有在你的钱大于等于qi时才可以买入,每件商品在你心目中都有价值vi。现在你有m元钱,如何实现使买到的商品价值最大。下面我举题目中给出的例子进行分析,逐个击破。
3 10 ----分别是商品件数和Money5 10 5 ----A商品的价格,最低入手价,价值3 5 6 ----B商品2 7 3 ----C商品答案是11。正确的解法是先买A,再买B。这样就可以买到的价值是11,5+6=11。你会发现其实这个买的顺序有关系,因为你不可以先买B再买A,这样就错了。但是如果qi和pi是相同的,那么就跟顺序没关系了。所以,我们先假设qi=pi,先把这个简单的问题解决。题目如下,其实就是把q省去了。
3 105 5 ----A商品3 6 ----B商品2 3 ----C商品这时,很多人想着把所有的情况都罗列出来,再一一比较,这是最容易想到,也是最耗时的方法,我们必须得优化。那么,有一种思路是这样的,对每件商品而言,你要么买,要么不买,这里必须得引入一个式子来说明问题。f(n,m):花m元买n样东西实现的最大价值。对于任意的f(n,m),都有下面这两种情况:情况一,你买了第n件商品,f(n, m)=f(n-1, m-pn)+vn,因为买了第n件商品,所以花费了pn元,也因此得到了vn的价值。f(n, m)就等于第n件商品的价值+用m-pn的钱去买n-1件商品的价值。这样问题就规模就变小了。情况二,你不买第n件商品,f(n, m)=f(n-1, m),也就是说f(n, m)等于你用m元钱去买n-1件商品实现的最大价值。这两种情况,哪个价值大,就取哪一种,所以f(n, m) = max(f(n-1, m-pn)+vn, f(n-1, m))。这便是这第一步的核心。根据这个式子,解题的表格设计如下
![](http://images.cnitblog.com/blog/457362/201301/14151959-e14dbba0afde4df09942d7b2f1fe8d1c.jpg)
3 105 5 5 ----A商品3 3 6 ----B商品2 3 3 ----C商品其实,就是让C商品的q不等于p,其他都相同,这时,你就会发现如果要买C商品的话,肯定得先买C商品,因为买C商品的代价最大。所以,我们可以按照qi-pi的顺序来确定大顺序。这里我们还可以用更严谨的方式来证明一下,比如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大的先买。这里还得注意一点就是,排序的时候,得按照qi-pi从小到大排序,因为你买第n件商品的时候,是在比较你是否要先买第n件商品。打个比方让大家更好地理解,比如说f(3,10),是不是max(f(2, 10-p3)+v3, f(2, 10)),你会发现这个第一种情况f(2,10-p3)+v3中,是先买了第三件商品,也就是说排在后面的商品会先买。好的,排好序之后,就把问题就转换为不需要考虑顺序的问题了,那就是上面我们已经解决0/1背包问题了。这样,问题圆满解决了。附上代码:
/*HDU 3466需要排序的01背包*/#include<stdio.h>#include<string.h>#include<algorithm>#include<iostream>using namespace std;const int MAXN=550;struct Node{int p,q,v;}node[MAXN];int dp[5500];bool cmp(Node a,Node b)//按照 q-p 从小到大排序{return a.q-a.p < b.q-b.p;}int main(){int n,m;while(scanf("%d%d",&n,&m)!=EOF){for(int i=0;i<n;i++)scanf("%d%d%d",&node[i].p,&node[i].q,&node[i].v);sort(node,node+n,cmp);memset(dp,0,sizeof(dp));for(int i=0;i<n;i++)for(int j=m;j>=node[i].q;j--)dp[j]=max(dp[j],dp[j-node[i].p]+node[i].v);printf("%d\n",dp[m]);}return 0;}
相关文章推荐
- Spark Streaming+Flume对接实验
- Spring @Transactional
- 数字转化英文字母
- strut 多文件上传
- 电子系统面临了哪些威胁?
- SVN版本回退
- android WakeLock 唤醒
- Apache Thrift - 可伸缩的跨语言服务开发框架
- hdoj.5078 Osu!【暴力】 2015/08/04
- Android实现推送方式解决方案
- RecyclerView 动画 (添加、删除动画 以及 加载item 时的动画)
- java.lang.ClassNotFoundException: Didn't find class "*****Activity" on path: /data/app/*******.apk
- 格林威治时间计算
- Acviticy.this 和 getApplicationContext()的区别
- nginx高级配置
- multiset应用
- 流行的编程语言和特性
- 希尔排序
- Android 开发 Log无输出
- 《HTML5移动web开发指南》