2.3阿里巴巴与四十大盗——背包问题

  • 2.3.1问题分析
  • 2.3.2算法设计
  • 2.3.3 完美图解
  • 2.3.4 伪代码详解
  • 2.3.5 实战演练
  • 2.3.6算法分析及优化拓展
    • 1.算法复杂度分析
    • 2.算法优化拓展

有一天,阿里巴巴赶着一头毛驴上山砍柴。砍好柴准备下山时,远处突然出现一股烟尘,弥漫着直向上空飞扬,朝他这儿卷过来,而且越来越近。靠近以后,他才看清原来是一支马队,他们共有四十人,一个个年轻力壮、行动敏捷。一个首领模样的人背负沉重的鞍袋,从丛林中一直来到那个大石头跟前,喃喃地说道:“芝麻,开门吧!”随着那个头目的喊声,大石头前突然出现一道宽阔的门路,于是强盗们鱼贯而入。阿里巴巴待在树上观察他们,直到他们走得无影无踪之后,才从树上下来。他大声喊道:“芝麻,开门吧!”他的喊声刚落,洞门立刻打开了。他小心翼翼地走了进去,一下子惊呆了,洞中堆满了财物,还有多得无法计数的金银珠宝,有的散堆在地上,有的盛在皮袋中。突然看见这么多的金银财富,阿里巴巴深信这肯定是一个强盗们数代经营、掠夺所积累起来的宝窟。为了让乡亲们开开眼界,见识一下这些宝物,他想一种宝物只拿一个,如果太重就用锤子凿开,但毛驴的运载能力是有限的,怎么才能用驴子运走最大价值的财宝分给穷人呢?
阿里巴巴陷入沉思中……

2.3.1问题分析

假设山洞中有n种宝物,每种宝物有一定重量w和相应的价值v,毛驴运载能力有限,只能运走m重量的宝物,一种宝物只能拿一样,宝物可以分割。那么怎么才能使毛驴运走宝物的价值最大呢?
我们可以尝试贪心策略:
(1)每次挑选价值最大的宝物装入背包,得到的结果是否最优?
(2)每次挑选重量最小的宝物装入,能否得到最优解?
(3)每次选取单位重量价值最大的宝物,能否使价值最高?
思考一下,如果选价值最大的宝物,但重量非常大,也是不行的,因为运载能力是有限的,所以第一种策略舍弃;如果选重量最小的物品装入,那么其价值不一定高,所以不能在总重限制的情况下保证价值最大,第二种策略舍弃;而第三种是每次选取单位重量价值最大的宝物,也就是说每次选择性价比(价值/重量)最高的宝物,如果可以达到运载重量m,那么一定能得到价值最大。
因此采用第三种贪心策略,每次从剩下的宝物中选择性价比最高的宝物。

2.3.2算法设计

(1)数据机构及初始化。将n种宝物的重量和价值存储到类Three(包含重量、价值、性价比3个成员)中,同时求出每种宝物的性价比也存储在对应的类Three中,将其按照性价比从高到低排序。采用jiazhi来存储毛驴能够运走的最大值,初始化为0。用zhongliang存储已装宝物的重量
(2)根据贪心策略,按照性价比从大到小选取宝物,直到达到毛驴的运载能力。每次选择性价比高的物品,判断是否小于m(毛驴的承载能力),如果小于m,则放入,jiazhi(已放入物品的价值)加上当前宝物的价值,zhongliang加上当前宝物的重量;如果不小于m,则取该宝物的一部分 (m-zhongliang) * i.per(当前背包剩余重量*宝物的单位价值),程序结束。zhongliang等于m,则jiazhi得到最大值。

2.3.3 完美图解

假设现有一批宝物,价值和重量如表2-3所示,毛驴运载能力m=30,那么怎么装入最大价值的物品?

(1)因为贪心策略师每次选择性价比(价值/重量)高的宝物,可以按照性价比降序排序,排序后如表2-4所示。

(2)按照贪心策略,每次选择性价比高的宝物放入:
第一次选择宝物2,剩余容量30-2=28,目前装入最大价值为8
第二次选择宝物10,剩余容量28-5=23,目前装入最大价值为8+15=23
第三次选择宝物6,剩余容量23-8=15,目前装入最大价值为23+20=43
第四次选择宝物3,剩余容量15-9=6,目前装入最大价值为43+18=61
第五次选择宝物5,剩余容量6-5=1,目前装入最大价值为61+8=69
第六次选择宝物8,发现上次处理完时剩余容量为1,二8号宝物重量为4,无法全部放入,那么可以采用部分装入的形式,装入一个重量单位,因为8号保护的单位重量价值为1.5,因此放入价值1*1.5=1.5,你也可以认为装入了8号宝物的1/4,目前装入最大价值为69+1.5=70.5,剩余容量为0
(3)构造最优解
把这些放入的宝物序号组合在一起,就得到了最优解(2,10,6,3,5,8),其中最后一个宝物为部分装入(装了8号财宝的1/4),能够装入宝物的最大价值为70.5

2.3.4 伪代码详解

(1)数据结构定义
根据算法设计中的数据结构,我们首先定义一个类Three:

class Three:def __init__(self, weight, value, per):self.weight = weight  # 每个宝物的重量self.value = value  # 每个宝物的价值self.per = per  # 性价比

(2)性价比排序
我们可以利用python中的排序函数sort,对宝物的性价比从大到小(非递增)排序。
在本例中我们采用类形式存储,因此采用自定义排序函数的方法实现宝物性价比低降序排序:

list_baowu.sort(key=lambda x: x.per, reverse=True)  # 根据per逆序排序

(3)贪心算法求解

for i in list_baowu:if zhongliang + i.weight < m:shuliang += 1jiazhi += i.valuezhongliang += i.weightelse:jiazhi += (m-zhongliang) * i.pershuliang += (m-zhongliang)/i.weightzhongliang = m

2.3.5 实战演练

class Three:def __init__(self, weight, value, per):self.weight = weight  # 每个宝物的重量self.value = value  # 每个宝物的价值self.per = per  # 性价比
n, m = input("请输入宝物的总数量和毛驴的承载能力:").split()
n = int(n)
m = float(m)
list_baowu = []  # 创建实例对象的空列表
for i in range(n):w, v = map(int, input("请分别输入宝物的重量和价值").split())list_baowu.append(Three(w, v, v/w))  # 根据每个对象的属性创建对象
list_baowu.sort(key=lambda x: x.per, reverse=True)  # 根据per逆序排序
shuliang = 0  # 可以装的宝物的数量
zhongliang = 0   # 已装的重量
jiazhi = 0  # 已装入的价值
for i in list_baowu:# print(i.per)if zhongliang + i.weight < m:shuliang += 1jiazhi += i.valuezhongliang += i.weightelse:jiazhi += (m-zhongliang) * i.pershuliang += (m-zhongliang)/i.weightzhongliang = m
print("Maxinum value = %.2f" % jiazhi)

2.3.6算法分析及优化拓展

1.算法复杂度分析

(1)时间复杂度:该算法的时间主要耗费在将宝物按照性价比排序上,采用的是快速排序,算法时间复杂度为O(nlogn)。
(2)空间复杂度:空间主要耗费在存储宝物的性价比,空间复杂度为O(n)。

2.算法优化拓展

那么想一想,如果宝物不可分割,贪心算法是否能得到最优解?
假定物品的重量和价值已知,如表2-5所示,最大运载能力为10.利用贪心算法会得到怎样的结果?

如果我们采用贪心算法,先装性价比高的物品,且物品不能分割,剩余容量如果无法再装入剩余的物品,不管还有没有运载能力,算法都会结束。那么我们选择的物品为1和2,总价值为31.但实际上我们如果选择物品2和3,正好达到运载能力,得到的最大价值为34。也就是说,在物品不可分割、没法装满的情况下,贪心算法并不能得到最优解,仅仅是最优解的近似解。
物品可分割的装载问题我们称为背包问题,物品不可分割点装载问题我们称之为0-1背包问题
想一想,2.3节中加勒比海盗船问题为什么在没有装满的情况下,仍然是最优解,而0-1背包问题在没装满的情况下有可能只是最优解的近似解?

# 0-1背包问题待补充
pass

2.3阿里巴巴与四十大盗——背包问题相关推荐

  1. 贪心算法之阿里巴巴与四十大盗——背包问题

    14天阅读挑战赛 有一天,阿里巴巴赶着一头毛驴上山砍柴.砍好柴准备下山时,远处突然出现一股烟尘,弥漫着向上空飞扬,朝他这儿卷过来,而且越来越近.阿里巴巴心里害怕,担心碰到的是一伙儿强盗,他赶紧把毛驴赶 ...

  2. 贪心算法--阿里巴巴与四十大盗--背包问题

    一.问题描述 有一天,阿里巴巴赶着一头毛驴上山砍柴.砍好柴准备下山时,远处突然出现一股烟尘,弥漫着直向上空非扬,朝他这儿卷过来,而且越来越近.靠近以后,他才看清原来是一支马队,他们公有四十人,一个个年 ...

  3. 【贪心算法】阿里巴巴与四十大盗——背包问题与0-1背包问题

    前言 关于贪心算法,我在这篇博客中已经做了简单的介绍.初识贪心算法 下面来介绍一下贪心算法中的一个经典的问题--背包问题 一.问题描述 一天,阿里巴巴赶着一头毛驴上山砍柴,无意间在远处发现了一群盗贼, ...

  4. 2.3阿里巴巴与四十大盗 背包问题

    有一天,阿里巴巴赶着一头毛驴上山砍柴.砍好柴准备下山时,远处突然出现一股烟尘,弥漫着直向上空飞扬,朝他这儿卷过来,而且越来越近.靠近以后,他才看清原来是一支马队,他们共有四十人,一个个年轻力壮.行动敏 ...

  5. 【贪心】阿里巴巴与四十大盗-背包问题

    题目 阿里巴巴因为偶然的机会进入了强盗们的宝库,他想拿走一些让乡亲们开开眼.他想每种宝物只拿一个,如果太重就用锤子凿开,但毛驴运载能力有限,怎么才能用毛驴运走最大价值的宝物呢? 数据 输入 第一行:宝 ...

  6. 阿里巴巴与四十大盗——背包问题

    C++源码: #include<iostream> #include<algorithm> #include<conio.h> const int M=100000 ...

  7. 贪心算法 | 背包问题——阿里巴巴与四十大盗

    2.背包问题--阿里巴巴与四十大盗 问题:有一天,阿里巴巴赶着一头毛驴上山砍柴.砍好柴准备下山时,远处突然出现一股烟尘,弥漫着直向上空非扬,朝他这儿卷过来,而且越来越近.靠近以后,他才看清原来是一支马 ...

  8. 贪心算法之阿里巴巴与四十大盗(背包问题)

    1.问题 有一天,阿里巴巴赶着一头毛驴上山砍柴.砍好柴准备下山时,远处突然出现一股烟尘,弥漫着直向上空飞扬,朝他这儿卷过来,而且越来越近.靠近以后,他才看清原来是一支马队,他们共有四十人,一个个年轻力 ...

  9. 贪心——阿里巴巴与四十大盗(可拆分背包)

    问题 F: 阿里巴巴与四十大盗 时间限制: 1 Sec  内存限制: 128 MB 提交: 215  解决: 123 [提交][状态][讨论版][命题人:quanxing] 题目描述 有一天,阿里巴巴 ...

最新文章

  1. shell awk实战
  2. 约瑟夫环的问题--剑指 Offer 62. 圆圈中最后剩下的数字
  3. menu什么意思中文意思_vigorous什么意思
  4. 一步一步手绘Spring DI运行时序图(Spring 自动装配之依赖注入)
  5. java 抽象类与接口的区别及其在jdk中的应用
  6. go sum: verifying module: checksum mismatch
  7. SourceInsight4.0的使用
  8. 微信红包雨怎么抢_微信红包雨怎么发? 微信红包雨的操作方法?
  9. nodejs中events模块的使用
  10. 这个夏天,我去过阳朔……
  11. Tracup丨什么是敏捷产品管理?
  12. 简单使用python进行图像打标
  13. 蚂蚁借“链”上位,BAT谁将成数字经济领跑者?
  14. bootstrap响应式布局
  15. stm8 RTC自动唤醒
  16. html flash闹钟,教你用Flash制作可以定时闹钟
  17. 多智能体强化学习:鼓励共享多智能体强化学习中的多样性
  18. python智慧树判断题_智慧树知到_大数据分析的python基础_判断题答案
  19. mysql2008和mysql2000_[转载]SQL 2008到2005和2000版本的转换
  20. 2018级全国计算机二级office试题,全国计算机二级真题-2018年全国计算机二级MsOffice精选真题试卷(Excel)...

热门文章

  1. matlab灰色预测弱化代码,灰色预测模型介绍及MATLAB代码实现
  2. 情人节挨打礼物-情侣头像自动生成
  3. 创新创业大赛发布攻略大全-创成汇
  4. 禾穗漫读 | 与自己和解:治愈你内心的内在小孩
  5. Shell Bash 使用jq 命令合并多个json文件以及去掉输出内容里面多余的双引号
  6. 字符串处理函数:sscanf 的用法
  7. 云尚,大健康时代的共享经济实践
  8. ROS1云课→02系统架构
  9. 7年级计算机组成ppt,《第二课_计算机的硬件软件了解计算机系统的组成课件》初中信息技术滇教科课标版七年级全一册课件.ppt...
  10. 【MATLAB-app】matlab appdesigner 设计中的几个神招数(精心打造,附源代码)