Proud Merchants(01背包变形)hdu3466
I - Proud Merchants
Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u
Description
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?
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.
Output
Sample Input
Sample Output
3 10 ----分别是商品件数和Money
5 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 10
5 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))。这便是这第一步的核心。
根据这个式子,解题的表格设计如下

f(n,m)中n表示商品的件数,m表示钱,而f(0,3)表示没有商品,你有3块钱的情况下,你可以买到的价值,那当然是0咯;在举个例子f(2,6),表示有2件商品,你有6块钱,那你比较来判断你要不要买第二件商品,如果你买了第二件商品,那么就是f(1, 6-3)+6=0+6=6;如果你不买第二件商品,那么就是f(1,6)=5。两种情况取大的,所以,你取6。其实,以上表格就是根据f(n, m) = max(f(n-1, m-pn)+vn, f(n-1, m))来得到的,多设计几组数据练几下就融会贯通了。这样第一步就算完成了,其实这就是0/1背包。
eg:
接下来针对有q的情况,这无疑是跟购买的顺序有关。我们不妨把大顺序确定下来。也就是说,比方说A、B、C三样商品,我们不管他买不买,我们只要确定下来如果他买,那肯定先买A再买C,那接下来是不是就不需要考虑顺序,只需要使用以上的0/1背包算法直接来。这就是我们的思路,先把顺序给考虑了,在套用以上0/1背包算法。我们还是举上面这个例子,我们稍微改一下,得到
3 10
5 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背包问题了。这样,问题圆满解决了。
代码如下
#include<cstdio>
#include<vector>
#include<algorithm>
#include<iostream>
using namespace std; int N,M;
struct node
{
int p,q,v,dp;
}a[]; int cmp(node x,node y)
{
return x.dp<y.dp;
}
int main()
{
int i,j;
while(scanf("%d%d",&N,&M)!=EOF)
{
int f[]={};
for(i=;i<N;i++)
{
scanf("%d%d%d",&a[i].p,&a[i].q,&a[i].v);
a[i].dp=a[i].q-a[i].p;
}
sort(a,a+N,cmp);
// for(i=;i<N;i++)
// printf("p=%d\tq=%d\tv=%d\n",a[i].p,a[i].q,a[i].v);
for(i=;i<N;i++)
{
for(j=M;j>=a[i].q;j--)
{
f[j]=max(f[j],f[j-a[i].p]+a[i].v);
}
}
printf("%d\n",f[M]);
}
return ;
}
Proud Merchants(01背包变形)hdu3466的更多相关文章
- hdu 3466 Proud Merchants 01背包变形
Proud Merchants Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others) ...
- Proud Merchants(01背包)
Proud Merchants Time Limit : 2000/1000ms (Java/Other) Memory Limit : 131072/65536K (Java/Other) To ...
- HDU 3466 Proud Merchants(01背包)
题目链接: 传送门 Proud Merchants Time Limit: 1000MS Memory Limit: 65536K Description Recently, iSea wen ...
- FZU 2214 Knapsack problem 01背包变形
题目链接:Knapsack problem 大意:给出T组测试数据,每组给出n个物品和最大容量w.然后依次给出n个物品的价值和体积. 问,最多能盛的物品价值和是多少? 思路:01背包变形,因为w太大, ...
- codeforce Gym 101102A Coins (01背包变形)
01背包变形,注意dp过程的时候就需要取膜,否则会出错. 代码如下: #include<iostream> #include<cstdio> #include<cstri ...
- HDU 2639 Bone Collector II(01背包变形【第K大最优解】)
Bone Collector II Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
- 【01背包变形】Robberies HDU 2955
http://acm.hdu.edu.cn/showproblem.php?pid=2955 [题意] 有一个强盗要去几个银行偷盗,他既想多抢点钱,又想尽量不被抓到.已知各个银行 的金钱数和被抓的概率 ...
- CF#214 C. Dima and Salad 01背包变形
C. Dima and Salad 题意 有n种水果,第i个水果有一个美味度ai和能量值bi,现在要选择部分水果做沙拉,假如此时选择了m个水果,要保证\(\frac{\sum_{i=1}^ma_i}{ ...
- HDU3466-Proud Merchants(01背包变形)
需要排序的01背包. 这种题排序时只需要考虑两个怎么排,重载小于号就可以了. 需要注意的是,如果一个物品你想先放进背包里,那么你排序是要放到后面!01背包的放置顺序的倒着的! 看到别人的博客都只是比较 ...
随机推荐
- 背水一战 Windows 10 (50) - 控件(集合类): ItemsControl - 基础知识, 数据绑定, ItemsPresenter, GridViewItemPresenter, ListViewItemPresenter
[源码下载] 背水一战 Windows 10 (50) - 控件(集合类): ItemsControl - 基础知识, 数据绑定, ItemsPresenter, GridViewItemPresen ...
- Spring AOP 源码分析系列文章导读
1. 简介 前一段时间,我学习了 Spring IOC 容器方面的源码,并写了数篇文章对此进行讲解.在写完 Spring IOC 容器源码分析系列文章中的最后一篇后,没敢懈怠,趁热打铁,花了3天时间阅 ...
- CentOS 7 - 配置服务实现开机自启动
新建系统服务描述文件 cd /etc/systemd/system sudo vim myapp.service 添加以下配置: [Unit] # 这里添加你的服务描述 Description=mya ...
- [BeiJing wc2012]连连看(建模,最小费用最大流)
前言 突然发现自己在图论①被dalao吊着打... Solution 看到数据范围1000,感觉可以直接枚举连边,然后新建两个点就好了. 注意要拆点,不然可能会死循环(过来人) 代码实现 #inclu ...
- 优化openfire服务器提升xmpp 效率的15个方法(原创)
1.禁用原生xmpp搜索,使组织架构.人员数据本地化保存,并使客户端数据同步服务器,降低原生xmpp搜索的iq消耗,因为搜索是im应用的频繁操作: 2.禁用roster花名册.禁用presence包通 ...
- Go指南练习 rot13Reader
题目: 练习:rot13Reader 有种常见的模式是一个 io.Reader 包装另一个 io.Reader,然后通过某种方式修改其数据流. 例如,gzip.NewReader 函数接受一个 io. ...
- Facade外观模式(结构性模式)
1.系统的复杂度 需求:开发一个坦克模拟系统用于模拟坦克车在各种作战环境中的行为,其中坦克系统由引擎.控制器.车轮等各子系统构成.然后由对应的子系统调用. 常规的设计如下: #region 坦克系统组 ...
- pycharm格式化代码 常用快捷键
ctrl+alt+L 一 常用快捷键 编辑类: Ctrl + D 复制选定的区域或行Ctrl + Y 删除选定的行Ctrl + Alt + L 代码 ...
- 常见数据结构的Java实现
单链表的Java实现 首先参考wiki上的单链表说明,单链表每个节点包含数据和指向链表中下一个节点的指针或引用.然后看代码 import java.lang.*; public class Singl ...
- 03-01:springboot 整合jsp
1.修改pom文件,添加坐标 <!-- jstl --> <dependency> <groupId>javax.servlet ...