人不能贪婪,但程序可以!用通俗的方法读懂贪心算法核心思想

前言

问:怎么把无数个不同重量且价值高低不等的物品装入承重有限的背包里才是最赚的?
答:哪个价值高先拿哪个!不够装就换第二价值高继续拿!直到背包装不下最小重量的物品为止!

以上问答环节的内容即贪心算法的核心思维。

一、通过经典题目理解

1、完全背包问题

有 N 种物品和一个容量为 V 的背包,每种物品都有无限件可用。第 i 种物品的体积是 c,价值是 w。
求解将哪些物品装入背包可使这些物品的体积总和不超过背包容量,且价值总和最大。

输入:
50
5
40 10 30 20 5
500 200 400 450 20

分析输入数据

  1. 输入第一行50即为背包最大容量V
  2. 第二行55种物品
  3. 最后两行分别为第 i 种物品的体积 c 与价值 w

解决问题步骤分解

以上输入数据可以得出以下图示,图示是较好的表达程序运行过程的方法之一。

在这里插入图片描述
还是遵循前言问答的思想:哪个价值高先拿哪个!不够装就换第二价值高继续拿!直到背包装不下最小重量的物品为止!
所以下一步,应是挑选价值最大(红色)的物品将其放入背包容器。

在这里插入图片描述
放入以后,背包容器的剩余体积只有10了,第二高价值(蓝色)的物品所需体积要20,所以只能继续跳过,拿第三高价值(绿色)的物品,所需体积要30不足以装入背包容器,继续跳过,以此类推,直到拿到体积为10,价值为200(黄色)的物品,将其放入。

在这里插入图片描述
到此背包已经没办法继续放入其他物品了,程序的贪婪模式结束,它认定自己最赚的拿法就是能拿到价值为700的物品。但是不难发现,此解并非最优解

并非最优解

我们仔细思考一下,确实最优解是最大能拿到价值为1100的物品。

在这里插入图片描述
难道贪心算法并不是对所有问题都能得到整体的最优解?还是说这只是一个特殊的巧合?我们继续往下看。

2、找零问题

有 i 种币值为 w 以及相应的数量 c ,用最少的数量凑齐一定的金额 t 。

输入:
172
7
1 2 5 10 20 50 100
3 3 2 1 1 3 3

分析输入数据

  1. 输入第一行172即为需要找回的零钱总数
  2. 第二行7即为7种纸币类型
  3. 第三行为7种纸币的面值
  4. 第四行为对应7种纸币的数量

解决问题步骤分解

以上输入数据可转化为以下图示。

在这里插入图片描述
我们还是遵循贪心算法的思想,要使得找回的钱币数量最少,直接从最大的拿不就完事儿了嘛。

在这里插入图片描述
先拿最大面值的100元纸币放入槽中,剩余要找回的零钱数还剩下72,由于72 < 100,所以不能再拿100元纸币放入,只能拿50元纸币

在这里插入图片描述
50元纸币放入槽后,此时可以看到目前还需要找零的22元,所以继续分别选取20元纸币2元纸币各一张。

在这里插入图片描述
最终,找回零钱数为0,即已经完成找零。可以看到我们使用了四张纸币,完成了这一次找零。但是可以思考一下,这是最佳的找零方案了吗,如果是最佳方案,那还有别的情况会导致找零问题得不到最优解吗?答案当然是有的

并非所有情况都能得到最优解

我们给定下面这组输入数据,尝试用贪心算法执行一遍。

输入:
10
3
1 5 7
3 2 1

现在有三种面值纸币,分别是1元纸币5元纸币7元纸币,数量分别是321。我们需要找零10元给菜市场大妈,怎么才能使得找回纸币数量最小?

在这里插入图片描述
还是按照贪心算法得思路来,首先拿最大的7元纸币放入槽中。

在这里插入图片描述
此时还需要找零3元,所以我们以此把三张1元纸币放入槽中。

在这里插入图片描述
此时使用了四张纸币,完成了这一次找零,但是问题来了,这并不是这次找零方案的最优解,因为我们知道,只需要使用两张5元纸币足矣。
在这里插入图片描述
贪心算法真的确实不是对所有问题都能得到整体的最优解,到底是什么导致这种情况发生?

二、为什么贪心算法得不到最优解?

原因就在于贪心算法局部最优解原则,它的决策手段即做出在当前看来是最好的选择,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解,得出来的结果有可能是最优解,也有可能得到是近似解

它的具体算法过程是采用自顶向下,以迭代的方法做出相继的贪心选择,每做一次贪心选择,就将所求问题简化为一个规模更小的子问题,通过每一步贪心选择,可得到问题的一个最优解。但大家都知道,并非所有问题都能使用贪心算法求最优解

所以我们使用贪心算法时,一定要注意以下贪心算法的特点:
1、不能保证解是最佳的。因为贪心算法总是从局部出发,并没从整体考虑。
2、贪心算法一般用来解决求最大或最小解。
3、贪心算法只能确定某些问题的可行性范围。

三、总结一下

其实背包问题的最优解一般是使用动态规划进行求解而并非贪心算法,因为贪心算法局部最优解原则,使得只能确定问题的可行性范围,也仅仅是一个范围。

使用贪心算法解决背包问题与找零问题的python程序已经上传到gitee。有兴趣的小伙伴可以看看。

《码农小易 - gitee - 贪心算法解完全背包问题》
《码农小易 - gitee - 贪心算法解找零问题》

图文均为原创,如果你觉得文章对你帮助,记得点赞关注一下哦。

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农小易

你的鼓励将是我持续写作的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值