又是一个阳光明媚的周末,是一个出去游玩的好日子。
小明背上书包,和他的好朋友丁丁一起去郊外游玩。
郊外芳草青青,流水潺潺。真是一个游玩的好地方啊!
正当小明和丁丁玩的正High的时候,突然间冒出来一个披头散发的老乞丐,把小明和丁丁吓个半死。
老乞丐突然从身后拿出一本书,上面赫然写着4个大字——“如来神掌”!


老乞丐对小明说:“小朋友啊,我看你相貌不凡,骨骼惊奇,是一个练武奇才。我这里有一本《如来神掌》,五块钱卖给你修炼如何?”
小明摆出一股不屑的表情,用拇指查了一下鼻子,说:“我不要!”
老乞丐看小明的表情如此坚决,无奈之下掏出了自己的所有家底:《如来神掌》、《降龙十八掌》、《六脉神剑》、《葵花宝典》、《凌波微步》、《蛤蟆功》、《黯然销魂掌》各一本。
老乞丐得意地看着这两个小朋友,说:“怕了你了,既然你不想学《如来神掌》,我这里还有别的武功秘籍,都是绝版的哦,江湖上就都只剩一本了。机不可失,失不再来,赶快下定离手!”
小明还是一股不屑的眼神,准备离开。
老乞丐无奈了,他深知这个小学生骨骼惊奇,如果学习了武功奖励一定能成为一代大侠,于是他做了一个他此生最重要的决定。“你要的话,全拿走吧,免费的。”
小明这才转过身来,准备全部拿走。
但是丁丁提醒小明:“小明,我们的书包不够大,最多只能装100页的书。”
小明这才想起来自己的书包不够装那么多数的事实。“啊,多么痛的领悟!”小明看到老乞丐手中的那些书,真是太多了,多到自己的书包都装不下了。
这个时候丁丁提醒小明:“我们可以尽量多装点书呀”
但是怎么装划算呢,小明不知道哪些书好那些书不好,这可愁死了他。
这个时候老乞丐发话了:“小朋友,这些书每一本都对应了一个武力值,当你学完了你本书的话你就能够增加相应的武力值。而这些武力值和书的价格是成正比的。比如这本《如来神掌》的价格是5元,那么当你学习了《如来神掌》之后,你的武力值就会增长5点。而这本《降龙十八掌》的价格是10元,也就是说……”。
“当我练完《降龙十八掌》之后,我的武力值将会增加10点!”小明说到。
老乞丐听到如此精确的回答,不禁肃然起敬,心想眼前的这位小学生不仅骨骼惊奇,连智力都高人一等。他赶忙回应道:“是的,不错。”
接下来老乞丐给两位小朋友列举了他手上所有的书的页数和价格。

书名 页数 价格
《如来神掌》 20 5
《降龙十八掌》 30 10
《六脉神剑》 10 6
《葵花宝典》 50 10
《凌波微步》 30 8
《蛤蟆功》 30 5
《黯然销魂掌》 20 20

小明和丁丁计算了一下,这些书地总页数加起来是20 + 30 + 10 + 50 + 30 + 30 + 20 = 190(页),是不可能把这些书全部都拿走的。
小明是一个爱思考的好孩子,于是他将买书的这件事情归纳为了如下的一个问题:
    取几本书使得这几本书的页数之和不超过100页,并且它们的价格之和尽可能地大。
那么怎么来解决这个问题呢,这可让小明和丁丁烦懵了。
这个时候你出现了,告诉小明和丁丁,这其实是一个“0-1背包问题”。
0-1背包问题的大致描述是这样的:
    有N件物品和一个容量为V的背包。第i件物品的体积是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。
这个问题为什么要在“背包”之前加一个“0-1”是因为对于每一个物品,它都只有两种状态:放进背包里面去了(对应状态1),或者没有放进背包里面去(对应状态0),所以称为“0-1背包问题”。
如果我们将故事中的每一本书对应成一个物品,将书的页数对应成物品的体积,将书的价格对应成物品的价值,那么连个问题就是一样的。
接下来我们来学习如何求解0-1背包问题。
0-1背包问题最基础的背包问题,它的特点是:每种物品仅有一件,可以选择放或不放。
用子问题定义状态:即f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值,可以得到它的状态转移方程:
    f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}
这个方程非常重要,基本上所有跟背包相关的问题的方程都是由它衍生出来的。所以有必要将它详细解释一下:“将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题。如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中”,价值为f[i-1][v];如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的容量为v-c[i]的背包中”,此时能获得的最大价值就是f[i-1][v-c[i]]再加上通过放入第i件物品获得的价值w[i]。

设物品的数量为N,背包的容量(如前所述)为V。以上方法的时间和空间复杂度为O(N*V),其中时间复杂度基本已经不能再优化了,但空间复杂度却可以优化到O(V)。
先考虑上面讲的基本思路如何实现,肯定是有一个主循环i=1..N,每次算出来二维数组f[i][0..V]的所有值。那么,如果只用一个数组f[0..V],能不能保证第i次循环结束后f[v]中表示的就是我们定义的状态f[i][v]呢?f[i][v]是由f[i-1][v]和f[i-1][v-c[i]]两个子问题递推而来,能否保证在推f[i][v]时(也即在第i次主循环中推f[v]时)能够得到f[i-1][v]和f[i-1][v-c[i]]的值呢?事实上,这要求在每次主循环中我们以v=V..0的顺序推f[v],这样才能保证推f[v]时f[v-c[i]]保存的是状态f[i-1][v-c[i]]的值。伪代码如下:

for i=1..N
for v=V..c[i]
f[v]=max{f[v],f[v-c[i]]+w[i]};

其中的f[v]=max{f[v],f[v-c[i]]}一句恰就相当于我们的转移方程f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]},因为现在的f[v-c[i]]就相当于原来的f[i-1][v-c[i]]。如果将v的循环顺序从上面的逆序改成顺序的话,那么则成了f[i][v]由f[i][v-c[i]]推知,与本题意不符,但它却是另一个重要的背包问题(完全背包问题)最简捷的解决方案,故学习只用一维数组解0-1背包问题是十分必要的。

根据对0-1背包问题的分析,再代入小明和丁丁的问题。可以得到:
    容器数组(对应页数) c 为 [20, 30, 10, 50, 30, 30, 20] 
    价值数组(对应价格) w 为 [ 5, 10, 6, 10, 8, 5, 20]
最终获得的价值为44,可以通过如下的C++代码实现:

#include <cstdio>
#include <iostream>
using namespace std;
int c[7] = {20, 30, 10, 50, 30, 30, 20};
int w[7] = { 5, 10,  6, 10,  8,  5, 20};
int N = 7, V = 100, f[101];
int main()
{
for (int i = 0; i < N; i ++)
for (int j = V; j >= c[i]; j --)
f[j] = max(f[j], f[j - c[i]]+w[i]);
int res = 0;
for (int i = 0; i <= V; i ++)
if (f[i] > res)
res = f[i];
printf("%d\n", res);
return 0;
}

小明顺利地拿走了基本武林秘籍。令人庆幸地是,他没有拿走那本《葵花宝典》。
后来又有人遇到了那个老乞丐,拿走了葵花宝典,从而在武林中掀起了一番惊风骇浪,欲知后事如何,请看电视剧《笑傲江湖》。
小明后来送给了丁丁那本《如来神掌》,丁丁历尽艰辛,最终成为了一位武功大师,与之详情,请看电影《功夫》。

0-1背包之小明和丁丁的奇遇相关推荐

  1. 【背包】小明逛超市(jzoj 2148)

    小明逛超市 题目大意: 有一个大小为n的背包,和m件物品,每件物品都有自己的价格和价值还有个数,当个数为0时则为无限件,为1实则为1件,求最大的价值 样例输入 4 5 5 3 0 5 3 1 4 4 ...

  2. 【Python】某商店T恤的价格为35元/件(2件9折,3件以上8折)裤子的价格为120元/条(2条以上9折).小明在该店买了3件T恤和2条裤子,请计算并显示小明应该付多少钱?

    #某商店T恤的价格为35元/件(2件9折,3件以上8折) # ,裤子的价格为120元/条(2条以上9折). # 小明在该店买了3件T恤和2条裤子,请计算并显示小明应该付多少钱? 解决·方案如下: a= ...

  3. HNUST OJ 2206 小明的衣服

    问题 C: 小明的衣服 时间限制: 1 Sec  内存限制: 128 MB 题目描述 小明有三件不用洗的神奇衣服.  第一件是T恤,他会在温度不超过30℃时穿着:  第二件是穿在T恤外的卫衣,他会在温 ...

  4. 小明学PostgreSQL : 自旋锁浅析

    <小明学PostgreSQL : 自旋锁浅析> Table of Contents 什么是自旋锁 自旋锁的伪码 TAS VS CAS PostgreSQL的自旋锁 什么是自旋锁 自从小明学 ...

  5. 二维费用 hdu 2159 FATE(完全背包)HDU OJ 4501 小明系列故事——买年货【DP】

    二维费用的背包问题是指:对于每件物品,具有两种不同的费用:选择这件物品必须同时付出这两种代价:对于每种代价都有一个可付出的最大值(背包容量).问怎样选择物品可以得到最大的价值.设这两种代价分别为代价1 ...

  6. HDUOJ----4501小明系列故事——买年货(三维背包)

    小明系列故事--买年货 Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Tota ...

  7. 小明打联盟 牛客(背包dp,多重背包)

    链接:https://ac.nowcoder.com/acm/problem/14553 来源:牛客网 题目描述 小明很喜欢打游戏,现在已知一个新英雄即将推出,他同样拥有四个技能,其中三个小技能的释放 ...

  8. hdu 4501 小明系列故事——买年货 多重背包

    小明系列故事--买年货                                                                          Time Limit: 500 ...

  9. 开心的小明 (NYOJ49) [动态规划.01背包]

    开心的小明 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 小明今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他 ...

最新文章

  1. Dialog外部点击事件
  2. python获取数组中大于某一阈值的那些索引值_使用Python+OpenCV进行实时车道检测...
  3. Css兼容:如何解决IE7和IE8的BUG
  4. getresourceasstream 路径_Java 获取资源文件路径
  5. 01背包和完全背包 的完整讲解版 包含 一维数组实现 和二维数组实现题目
  6. 译文-Minor GC vs Major GC vs Full GC
  7. sklearn——决策树基础概念
  8. 平板竖屏_朱海舟吐槽iPad办公体验:大量竖屏应用缺乏适配
  9. 智慧档案馆之区级档案库房温湿度智能化监控系统案例(一)
  10. STM32学习记录——SIM900A实现中英文短信发送
  11. 方波信号小波去噪matlab,Matlab小波去噪
  12. 生存分析(Survival Analysis)、Cox风险比例回归模型(Cox proportional hazards model)及
  13. 前端的性能优化-笔记
  14. dango-orm单表操作知识点
  15. 正则表达式学习——(2)正则回溯
  16. 软碟通(UltraISO注册码) v9.5.3.2901汉化版
  17. 最老程序员创业札记:全文检索、数据挖掘、推荐引擎应用43
  18. 图论(八)——割边割点和块
  19. ImageView加载网络图片
  20. javascript完成:使用split()和join()实现对输入文字设置背景颜色

热门文章

  1. 抖音服务器不稳定,抖音服务器崩了吗 看不了直播点不了赞差点逼疯网友
  2. STM32读取MQ4传感器、DHT11温湿度传感器、GP2Y1014AU0F夏普光学灰尘传感器数据
  3. 阿里云联手优酷推出工程师必看电影片单,高分烧脑假期必备!
  4. 【天光学术】主题班会讲话稿:勤俭节约,打造低碳生活
  5. 腾讯QQgame高性能服务器集群架构看分布式架构设计原则
  6. Python开发爬虫完整代码解析
  7. 计算机在线使用幻映片,几个计算机大一考试的选择题大家帮帮忙```
  8. 【js splice和slice】
  9. 传奇私服脚本大全2 加精
  10. leetcode 853. 车队