贪婪算法:
目标:不追求最优解,只希望得到较为满意解。
适用场景:简单问题,问题的解决方案的独立型好
定义:是采用逐步构造最优解的方法,即在每一个阶段,都做出一个看上去最优的决策;决策一旦做出,就不可再更改。
结构:
候选方案(CandidateSet)有一套可以解决问题的候选方案
选择函数(SelectionFunction)选择最优候选方案
可行性函数(FeasibilityFunction)确定是否可用某个候选方案
目标函数(ObjectiveFunction)用于判定整体的或者某个阶段的结果好坏
结果函数(SolutionFunction)用于结束
示例:
4件物品,其重量分别为w=[2,4,6,7],要求从中取出几件物品装入背包,且总重量不能超过c=7。
解决方案:
C#代码实现如下:
商品对象:
|
贪婪算法实现体:
|
方法调用:
|
输出结果:
上例解决的是最简单的贪婪例子,但实际应用中,这类简单的问题比例比较小,我们很多时候遇到的是np问题,例如,在上面的例子中为商品加入价值属性,我们将目标函数改成价值总和最大,那么我们上面的解决方案将失效。为此我们不得不引入k阶贪婪算法,其实k阶贪婪算法并不是什么新概念,其实就是数学上面的子集使用而已。
例如对于n的贪婪问题,k阶贪婪算法的子集个数其实就是而已。例如对于上面的例子,k=0时,则子集为null,后面直接使用一般贪婪法就是我们上面的解决方案,当k=1的时候,我们就具有{1}{2}{3}{4}四个子集,以每一个子集为第一个进箱,然后按照np中的密度算法将其余非递减排序后直接使用一般贪婪算法思想既可以。如果k=2,那么子集就是六个,{1,2}{1,3}{1,4}{2,3}{2,4}{3,4}。那么k=3的也类似,k=4那么就是全部了。其实如果你遍历k=0到k=n的所有情况,那么运算次数其实就是2的n次方。如果运用递归选择最优解的话,那么运行次数将是n的阶乘。当随着n增大的时候,那么贪婪法的优势将会越来越明显,因为贪婪法的事件耗费是指数增长,而遍历的时间耗费是阶乘增长,完全不是一个量级的。所以除非逼不得已的情况下,例如物理上面求解波函数的时候,以势能作为目标函数的时候,那么只能球的精确解,因为波的原因,精确解与近似解的x差距可能十万步千里,最终的图谱将会完全不同,这个时候只能求最优解,至于算法,主要就是惩罚函数的算法了,那个在数值解法里面由很详细的说明。