I - Proud Merchants

Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u

Description

Recently, 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?

 

Input

There 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.

 

Output

For each test case, output one integer, indicating maximum value iSea could get.

 

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
 
 
 
 
题意:有n件商品,每件商品的价格是pi,每件商品只有在你的钱大于等于qi时才可以买入,每件商品在你心目中都有价值vi。
    现在你有m元钱,如何实现使买到的商品价值最大。下面我举题目中给出的例子进行分析,逐个击破。
 
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背包问题了。这样,问题圆满解决了。

代码如下

 
 
那么既然我们要从尽量让价值最大,就要先考虑q与p的值相差大的,所以我们可以排个序,但是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的更多相关文章

  1. hdu 3466 Proud Merchants 01背包变形

    Proud Merchants Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) ...

  2. Proud Merchants(01背包)

    Proud Merchants Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other) To ...

  3. HDU 3466 Proud Merchants(01背包)

    题目链接: 传送门 Proud Merchants Time Limit: 1000MS     Memory Limit: 65536K Description Recently, iSea wen ...

  4. FZU 2214 Knapsack problem 01背包变形

    题目链接:Knapsack problem 大意:给出T组测试数据,每组给出n个物品和最大容量w.然后依次给出n个物品的价值和体积. 问,最多能盛的物品价值和是多少? 思路:01背包变形,因为w太大, ...

  5. codeforce Gym 101102A Coins (01背包变形)

    01背包变形,注意dp过程的时候就需要取膜,否则会出错. 代码如下: #include<iostream> #include<cstdio> #include<cstri ...

  6. HDU 2639 Bone Collector II(01背包变形【第K大最优解】)

    Bone Collector II Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  7. 【01背包变形】Robberies HDU 2955

    http://acm.hdu.edu.cn/showproblem.php?pid=2955 [题意] 有一个强盗要去几个银行偷盗,他既想多抢点钱,又想尽量不被抓到.已知各个银行 的金钱数和被抓的概率 ...

  8. CF#214 C. Dima and Salad 01背包变形

    C. Dima and Salad 题意 有n种水果,第i个水果有一个美味度ai和能量值bi,现在要选择部分水果做沙拉,假如此时选择了m个水果,要保证\(\frac{\sum_{i=1}^ma_i}{ ...

  9. HDU3466-Proud Merchants(01背包变形)

    需要排序的01背包. 这种题排序时只需要考虑两个怎么排,重载小于号就可以了. 需要注意的是,如果一个物品你想先放进背包里,那么你排序是要放到后面!01背包的放置顺序的倒着的! 看到别人的博客都只是比较 ...

随机推荐

  1. ASP.Net MVC OA项目笔记<一>

    1.1.1 新建空白解决方案CZBK.ItcastOA 1.2.1 添加类库 1.2.2 同上添加多个类库 生成的 class1.cs先不用删除,删了的后,后面可能没办法直接点引用 1.3.1 添加表 ...

  2. 背水一战 Windows 10 (51) - 控件(集合类): ItemsControl - 项模板选择器, 数据分组

    [源码下载] 背水一战 Windows 10 (51) - 控件(集合类): ItemsControl - 项模板选择器, 数据分组 作者:webabcd 介绍背水一战 Windows 10 之 控件 ...

  3. spring cloud学习(四) 动态路由

    Zuul的主要功能是路由和过滤器.路由功能是微服务的一部分,zuul实现了负载均衡. 1.1 新建模块zuul pom.xml <?xml version="1.0" enc ...

  4. Python大黑阔—url采集+exp验证,带你批量测试

    i春秋作家:大木瓜 前言: 最近几天在整理从各处收集来的各种工具包,大大小小的塞满了十几个G的硬盘,无意间发现了一个好几年前的0day.心血来潮就拿去试了一下,没想到真的还可以用,不过那些站点都已经老 ...

  5. Smart/400开发上手5: Cobol开发标准

    ENVIRONMENT DIVISION. CONFIGURATION SECTION.SOURCE-COMPUTER. IBM-AS400.OBJECT-COMPUTER. IBM-AS400. 这 ...

  6. 跨站脚本攻击(xss)理解

    一  概念 攻击者不直接攻击受害者,而是利用受害者登陆的网站中的漏洞,对受害者进行攻击. 二  危害 由于js本身的限制,并不能直接对用户的电脑造成侵害,但是可以: 1. 获取用户的storage,c ...

  7. C# 多线程学习系列二

    一.关于前台线程和后台线程 1.简介 CLR中线程分为两种类型,一种是前台线程.另一种是后台线程. 前台线程:应用程序的主线程.Thread构造的线程都默认为前台线程 后台线程:线程池线程都为后台线程 ...

  8. c++的动态绑定和静态绑定

    为了支持c++的多态性,才用了动态绑定和静态绑定. 1.对象的静态类型:对象在声明时采用的类型.是在编译期确定的. 2.对象的动态类型:目前所指对象的声明.在运行期决定.对象的动态类型可以更改,但是静 ...

  9. GO入门——4. 数组、切片与map

    1. 数组 定义数组的格式:var [n],n>=0 数组长度也是类型的一部分,因此具有不同长度的数组为不同类型 注意区分指向数组的指针和指针数组 //数组的指针 a := [2]int{1, ...

  10. PHP设计模式:观察者模式

    示例代码详见https://github.com/52fhy/design_patterns 观察者模式 观察者模式(Observer)是对象的行为模式,又叫发布-订阅(Publish/Subscri ...