贪心
贪心
简介
贪心算法(英语:greedy algorithm),是用计算机来模拟一个“贪心”的人做出决策的过程。这个人十分贪婪,每一步行动总是按某种指标选取最优的操作。而且他目光短浅,总是只看眼前,并不考虑以后可能造成的影响。
可想而知,并不是所有的时候贪心法都能获得最优解,所以一般使用贪心法的时候,都要确保自己能证明其正确性。 ——oi.wiki
贪心算法一般用于最优子结构问题,即为可以将一个问题拆分为多个子问题,由每个子问题的最优解可以推出整个问题的最优解。
特点
1.贪心选择
所谓贪心选择是说应用同一规则,将原问题变为一个相似的但规模更小的子问题,后面的每一步都是看目前的最佳选择,只依赖于已做出的选择,不依赖未作出的选择。
如背包问题,对于部分背包问题,是可以用贪心优先选择性价比高的,但对于这种不可分割物品的背包问题,却显然不能用贪心来做了,就比如说:
体积:100, 物品1:10 1, 物品2:100 100
如果按照贪心策略应该选物品一,这样就选不了物品二了,最大利益是 10, 而应该是只装物品二,最大利益 100 。此时显然贪心策略是错的了,因为它还要依赖其他物品,这时应该用动态规划解题。
2.最优子结构
执行算法时,每一次得到的结果虽然都是目前的最优解,但只有满足全局最优解包含局部最优解时,才能保证贪心算法正确。
证明方法
因为贪心往往不是正解,所以在使用贪心时往往要证明其正确性,而且有时证明其正确性时可以推出如何贪心(如国王游戏)。
证明贪心方法有两种:反证法和归纳法。很多基于贪心的算法也是通过这两种方法证明。
1.反证法
对于目前采取的贪心策略,定下一种交换方案,如果按照这种交换方案交换两个元素后,方案没有变得更优,那么说明目前的贪心策略是对的。
如求最小生成树的 \(Kruskal\) 算法其正确性就是反证法证明的。
2.归纳法
先算得出边界情况(例如 \(n == 1\) )的最优解 \(F_1\),然后再证明:对于每个 \(n\),\(F_{n + 1}\) 都可以由 \(F_n\) 推导出结果。
一些经典例题
1.最优装载问题
给定 \(n\) 个物品,第 \(i\) 个物品的重量是 \(w_i\) ,选择尽量多的物品,使总重量不多于 \(C\) 。
【贪心策略】 : 优先选择最轻的。
2.部分背包问题
与上一个例子不同,本题还加入了一个价值 \(v_i\) ,所以用 \(\frac{v_i}{w_i}\) 来表示一件物品的性价比。
【贪心策略】 : 优先选择性价比高的。
3.乘船问题
有 \(n\) 个人,第 \(i\) 个人重量为 \(w_i\) 。每艘船最大载重量为 \(C\) ,最多盛两个人。求如何用最少的船装载所有人。
【贪心策略】 : 对于任意一个人,应该选择能和他一起坐船的人中最重的一个。
4.选择不相交区间
给定 \(n\) 个开区间 \((a_i, b_i)\),选择尽量多的区间,使得他们两两没有公共点。
【贪心策略】 :
5.区间覆盖问题
给定 \(n\) 个闭区间 \([a_i, b_i]\) ,选择尽量少的区间,使其完全覆盖给定区间。

浙公网安备 33010602011771号