贪心算法
一、概念
贪心算法,又称贪婪算法,是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。
贪心选择:
贪心选择是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。贪心选择是采用从顶向下、以迭代的方法做出相继选择,每做一次贪心选择就将所求问题简化为一个规模更小的子问题。对于一个具体问题,要确定它是否具有贪心选择的性质,我们必须证明每一步所作的贪心选择最终能得到问题的最优解。通常可以首先证明问题的一个整体最优解,是从贪心选择开始的,而且作了贪心选择后,原问题简化为一个规模更小的类似子问题。然后,用数学归纳法证明,通过每一步贪心选择,最终可得到问题的一个整体最优解。
最优子结构:
当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。运用贪心策略在每一次转化时都取得了最优解。问题的最优子结构性质是该问题可用贪心算法或动态规划算法求解的关键特征。贪心算法的每一次操作都对结果产生直接影响,而动态规划则不是。贪心算法对每个子问题的解决方案都做出选择,不能回退;动态规划则会根据以前的选择结果对当前进行选择,有回退功能。动态规划主要运用于二维或三维问题,而贪心一般是一维问题。
局部最优解 ==> 整体最优解
二、思路
1.建立数学模型来描述问题;
2.把求解的问题分成若干个子问题;
3.对每一子问题求解,得到子问题的局部最优解;
4.把子问题的解局部最优解合成原来解问题的一个解。
三、特性
贪心算法可解决的问题通常都有如下的特性:
- 随着算法的进行,将积累起其它两个集合:一个包含已经被考虑过并被选出的候选对象,另一个包含已经被考虑过但被丢弃的候选对象。
- 有一个函数来检查一个候选对象的集合是否提供了问题的解答。该函数不考虑此时的解决方法是否最优。
- 还有一个函数检查是否一个候选对象的集合是可行的,也即是否可能往该集合上添加更多的候选对象以获得一个解。和上一个函数一样,此时不考虑解决方法的最优性。
- 选择函数可以指出哪一个剩余的候选对象最有希望构成问题的解。
- 最后,目标函数给出解的值。
- 为了解决问题,需要寻找一个构成解的候选对象集合,它可以优化目标函数,贪心算法一步一步的进行。起初,算法选出的候选对象的集合为空。接下来的每一步中,根据选择函数,算法从剩余候选对象中选出最有希望构成解的对象。如果集合中加上该对象后不可行,那么该对象就被丢弃并不再考虑;否则就加到集合里。每一次都扩充集合,并检查该集合是否构成解。如果贪心算法正确工作,那么找到的第一个解通常是最优的。
四、应用
0-1背包问题
题目
有一个背包,容量为M。有n个物品,每个重量为w,价值为v,物品不可以分割成任意大小。要求尽可能让装入背包中的物品总价值最大,但不能超过总容量。
分析
目标函数:∑vi最大
约束条件是装入的物品总重量不超过背包容量:∑wi<=M
贪心策略1:每次挑选价值最大的物品装入背包。
贪心策略2:每次挑选重量最小的物品装入背包。
贪心策略3:每次挑选单位重量价值最大的物品装入背包。
贪心算法是很常见的算法之一,这是由于它简单易行,构造贪心策略不是很困难。但是它需要证明后才能真正运用到题目的算法中。一般来说,贪心算法的证明围绕着:整个问题的最优解一定由贪心策略中存在的子问题的最优解得来的。
对于以上3种贪心策略,都是无法成立,以下是反证过程:
-
贪心策略1:每次挑选价值最大
反例:
W=30
物品:A B C
重量:30 20 10
价值:15 10 10
根据策略,选取A,可是选取B、C则更好。 -
贪心策略2:每次挑选重量最小
反例:
W=30
物品:A B C
重量:30 20 10
价值:25 10 10
根据策略,选取B、C,可是选取A则更好。 -
贪心策略3:每次挑选单位重量价值最大
反例:
W=30
物品:A B C
重量:20 15 15
价值:30 20 20
根据策略,选取A,可是选取B、C则更好。
注意:本题是个动态规划问题,用贪心算法并不一定可以求得最优解,以后了解了动态规划算法后本题就有了新的解法。