原文内容来自《计算机算法设计与分析 王晓东配套PPT》
用贪心法求解问题应该考虑如下几个方面:
(1)候选集合C:为了构造问题的解决方案,有一个候选集合C作为问题的可能解,即问题的最终解均取自于候选集合C。例如在找零钱问题中,各种面值的货币构成候选集合。
(2)解集合S:随着贪心选择的进行,解集合S不断扩展,直到构成一个满足问题的完整解。例如在找零钱问题中,已付出的货币构成解集合。
3)可行解函数solution:检查解集合S是否构成问题的一个可行解。例如,在找零钱问题中,可行解函数是已付出的货币金额恰好等于应找零钱。
(4)选择函数select:即贪心策略,这是贪心法的关键,它指出哪个候选对象最有希望构成问题的解,选择函数通常和目标函数有关。例如,在找零钱问题中,贪心策略就是在候选集合中选择面值最大的货币。
(5)约束函数constraint:检查解集合中加入一个候选对象是否满足约束条件。例如,在找零钱问题中,约束函数是每一步选择的货币和已付出的货币相加不超过应找零钱。
贪心算法的一般框架:
Greedy(C) //C是问题的输入集合即候选集合
{
S={ }; //初始解集合为空集
while (not solution(S)) //集合S没有构成问题的一个可行解
{
x=select(C); //在候选集合C中做贪心选择
if constraint(S, x) //判断集合S中加入x后是否满足约束条件
S=S+{x};
C=C-{x};
}
return S;
}
基本思想
从问题的某一个初始解出发,通过一系列的贪心选择——当前状态下的局部最优选择,逐步逼近给定的目标,尽可能快地求得更好的解。
在贪心算法(greedy method)中采用逐步构造最优解的方法。在每个阶段,都作出一个按某个评价函数最优的决策,该最优评价函数称为贪心准则(greedy criterion)。
贪心算法的正确性,就是要证明按贪心准则求得的解是全局最优解。
基本步骤
①决定问题的最优子结构
②设计出一个递归解
③证明在递归的任一阶段,最优选择之一总是贪心选择。那么,做贪心选择总是安全的。
④证明通过做贪心选择,所有子问题(除一个以外)都为空。
⑤设计出一个实现贪心策略的递归算法。
⑥将递归算法转换成迭代算法。
动态规划算法通常以自底向上的方式解各子问题,而贪心算法则通常以自顶向下的方式进行,以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。
对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。
当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。
问题的最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征。
贪心算法和动态规划算法都要求问题具有最优子结构性质,这是2类算法的一个共同点。
贪心算法和动态规划算法的区别:
动态规划法
每一步的选择是根据子问题的解做出的
先解决子问题
自底向上
复杂,慢
贪心算法
每一步都快速地做出当前最优选择-局部最优(贪心)选择
先做贪心选择再解决子问题
向顶向下
简单,快