算法导论随笔(六):贪心算法Greedy algorithm与分数背包问题(附Python实现源码)

本文探讨了贪心算法的概念及其在解决分数背包问题中的应用。通过一个答题游戏示例解释了贪心算法如何寻找每一步的局部最优解。接着详细介绍了分数背包问题,提供了一个简单的实例,并给出Python实现的算法,复杂度为O(nlogn)。源码已上传至GitHub,可供下载和测试。
摘要由CSDN通过智能技术生成

上一篇文章中我介绍了霍夫曼编码,并提到了它是贪心算法的一个应用。这篇文章我继续来谈谈贪心算法和它解决的一个经典问题,分数背包问题

1.贪心算法

在《算法导论》中,对贪心算法是这样描述的:

求解最优化问题的算法通常需要经过一系列的步骤,在每个步骤都面临多种选择。贪心算法就是这样的算法,它在每一步都作出当时看起来是最佳的选择。也就是说,它总是作出局部最优的选择,寄希望这样的选择能导致全局最优解。

我们可以看出,贪心算法在每一步中只作出当时看起来是最佳的选择。也就是说,贪心算法并不能保证对于每一个问题都能得到最优解。不过,对于大部分问题来说,贪心算法确实可以得到最优解。例如下图中的例子:
在这里插入图片描述
假设有一个答题游戏,答题人的初始分数为5。在每一轮时,答题人可以从3道题里选择一道题作答。这里我们假设答题人很聪明,知道所有问题的答案。这3道题的分值分别为9分,8分和7分。那么如果答题人使用的是贪心算法,则他一定会选择分值为9分的题目。在第二轮时,选择12分的题目;在第三轮时,选择17分的题目。这样答题人最后的得分就是5+9+12+17=43分。

那么43分是否为答题人能获得的最高分值呢?答案是不一定。如果答题人在第一轮时选择7分的题目,而7分题目的三个子节点中有一道50分的题目呢?那么此时答题人的分数就已经超过了43分。这也就是为什么我们说贪心算法找到的并不一定是最优解。它得到的解只是在它看来每一轮的最优解,但每一轮的最优解加起来并不一定是最后答案的最优解。

2. 分数背包问题(fractional knapsack problem)

分数背包问题是一个可以使用贪心算法解决的问题,并且贪心算法可以得到这个问题的最优解。我这里用一个比书上更直接的例子来介绍分数背包问题。首先我们来看下面的图。在这里插入图片描述
图中有5瓶液体,分别标号为1,2,3,4,5。编号为1的液体有4毫升,每毫升价值3美元。所以该液体的总价值为12美元。类似地,编号2,3,4和5的液体,分别有8毫升,2毫升,6毫升和1毫升,而每毫升的价值分别为4,20,5,50美元,它们的总价值分别为32,40,30,50美元。

现在我们有一个10毫升的杯子,想从5个瓶子里取出共10毫升的液体,使得该10毫升液体的总价值最高

这就是分数背包问题。这个10毫升的瓶子就是 “背包” ,我们要从5个瓶子里取出价值最高的液体塞满这个“背包”。而 “分数” 的意思是,对于5个瓶子中的液体,在取出其中一个瓶子的液体时,我们可以只取出一部分,而不需要全部取出。例如编号为2的瓶子里面有8毫升液体,我们可以选择取出8毫升,也可以选择只取出3毫升,也可以取出0毫升。

跟分数背包问题对应的是0-1背包问题。在0-1背包问题中,对于每个瓶子,我们要么就取出其所有的液体,要么就不取出液体。0-1背包问题并不能用贪心算法来解决

那么贪心算法是如何解决分数背包问题的呢?我们知道,贪心算法的主要思路是在每一步中都寻找该步骤的最优解。因此,首先要确定什么是每一步的最优解。对于上面的例子来说,在每一步中能拿到当前单位价值最高的液体,就是该步骤的最优解。用通俗的语言来说,就是先拿最贵的液体,等最贵的液体拿光了,再取第二贵的液体,然后再取第三贵的液体,以此类推。比如图中5号瓶的液体每毫升50美元,比其他液体的单位价值都贵,因此一定先拿5号液体。接着是3号,4号,2号…,直到已经拿到的液体总量达到10毫升为止。上面的问题比较简单,我们通过口算即可得到如下解法。
在这里插入图片描述
该算法的思想和我们的直觉相同,先拿最贵的,再拿相对贵的,最便宜的最后拿。该算法的伪代码如下。
在这里插入图片描述
算法的输入为一个集合S和背包重量上限W。S它包含了若干个物品;每个物品的总价值为bi,重量为wi。算法的输出为每个物品的id和取出该物品的重量。算法中的for循环通过以下公式计算每个物品单位重量的价值。
v i = b i / w i v_i = b_i / w_i v

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值