基础算法 —— 4. 贪心策略
方法论
对于某些优化问题,可以利用问题本身的特殊性质,使用贪心法通过不断寻找局部最优解从而找到全局最优解。贪心法与动态规划的最主要不同点在于状态转移时选择,动态规划总是需要确定多个可行的方案,而贪心法只有一个可行方案。
step:
- Cast the optimization problem as one in which we make a choice and are left
 with one subproblem to solve.
- Prove that there is always an optimal solution to the original problem that makes
 the greedy choice, so that the greedy choice is always safe.
- Demonstrate optimal substructure by showing that, having made the greedy
 choice, what remains is a subproblem with the property that if we combine an
 optimal solution to the subproblem with the greedy choice we have made, we
 arrive at an optimal solution to the original problem.
特点
Greedy versus dynamic programming: How can we tell whether a greedy algorithm will solve a particular optimization problem? No way works all the time, but the greedy-choice property and optimal substructure are the two key ingredients.
- 
Greedy-choice property: we make the choice that looks best in the current problem, without considering results from subproblems. Of course, we must prove that a greedy choice at each step yields a globally optimal solution. 
- 
Optimal substructure: A problem exhibits optimal substructure if an optimal solution to the problem contains within it optimal solutions to subproblems. All we really need to do is argue that an optimal solution to the subproblem, combined with the greedy choice already made, yields an optimal solution to the original problem. 
We can usually make the greedy choice more efficiently than when we have to consider a wider set of choices. By preprocessing the input or by using an appropriate data structure.
两个关键的要素:
贪心选择性质:所求问题的整体最优解可以通过局部最优解构造。换句话说,当进行选择时,我们直接做出局部最优解,而不必考虑全局解。
这也是贪心算法与动态规划的不同之处。动态规划中,为了保持全局最优,每个步骤做的选择通常都要依赖于子问题的解,所以一般采取自底向上实现。而贪心算法,我们总是选当下最优解,然后求解剩下的一个问题,在进行选择的时候不依赖于子问题,所以贪心算法一般都采取自顶向下实现。
我们需要证明每个步骤做出的贪心选择能够生成全局最优解。
如果进行选择间不得不考虑众多选择,通常意味着可以改进。例如活动安排问题,通过预处理,使活动结束时间保持非递减有序。
正确性的证明
有两种,数学归纳法 和 交换论证法
- 按步骤归纳
- 按规模归纳
- 交换论证
问题集
活动安排
其实就是求最大相容子集,我们的贪心策略是在剩下的活动中选择与已选活动相容,并且最早结束的。为了加速选择,我们可以预先将序列按结束时间进行排序。
最优装载问题
因为题目目标是求最多装载数,所以,可以采用轻者先装的策略。
哈夫曼编码
为了使平均码长最小,策略就是低频率对应大码长,也就是说优先先合并频率小的子树。
单源最短路径
Dijkstra 算法,其贪心策略是利用当前选中的点更新最短路径。也就是说初始设定一个点集,只有起点。不断往这个集合添加点,每添加了一个点,就检查是否因为它的引入,使得起点到其它点的最短路径变短,若是则更新。
最小生成树
Prim 算法:设置点集,初始含有一个点。寻找未在点集中,并且与点集中的点距离最小的点。
Kruskal 算法:选取满足不在同一连通分支的最小权值的边。
多机调度问题
这n 个任务必须都完成,并且开始时间和结束时间是固定的,求需要最少的机器。那么贪心策略就是**若有空闲机器,则直接将这个任务安排到空闲机器,

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号