算法(三):动态规划

不从定义等角度来考虑动态规划的含义,而只是从解决问题的思路上来说明如何将问题化繁为简。

问题特点

通过一个经典的动态规划来了解动态规划问题。
如下一个图,求出从起始点到终止点的最短路径:
算法(三):动态规划
初看起来,这个问题就是一个最短路径问题,使用迪杰斯特拉最短路径,或者弗洛伊德算法,甚至A*算法都可以完美求解。
但如果再仔细观察,就可以发现另一个特征,即阶段特征,上面的图的路径都是分为阶段的:
算法(三):动态规划
我们将路径剔除,但保留路径的连接关系,可以看出,原图可以分为4个阶段,相邻的阶段间有路径项链,阶段内部没有路径。
这也是动态规划的一般思路,即整体可以分为多个阶段,阶段与阶段间是相关的,通过阶段的迭代求解,得出最终结果。

问题求解

上面的问题可以如下求解:
从最后一个阶段开始,从后往前,求出当前阶段到下一阶段的最短路径,一直到第一个阶段:
算法(三):动态规划
1. 求出最后一个阶段到倒数第二个阶段的最短路径
算法(三):动态规划
2. 求出当前阶段到倒数第二阶段的最短路径
算法(三):动态规划
3. 问题的最后,求出最后的最短路径

体会求解过程与贪婪算法的不同,动态规划并没有子问题的解是总体的一部分这种特性,所以,并不能简单的套用贪婪算法。
通常来说,最有效的方法是能够使用图来表示动态规划问题,这样求解的方法就会一目了然。

总结:动态规划的全局最优不一定包含局部最优,因此每次的转台转移需要记录下之前的所有最优解;而贪心算法每一步的最优解都是全局最优的一部分。

问题延伸

最后以一个百度的笔试算法题最为结束:
小明上班的模式有两种——加班和不加班。加班的工资要比不加班要高,但加班后第二天不能上班,只能休息。给定每天的加班工资和不加班工资,求出最优的上班选择。
数据如下:
第一天:12 10
第二天:5 1
第三天:11 4
第四天:8 7

问题分析

这是个典型的动态规划问题,问题特点在于当天的选择只影响下一天的选择。通过分析这种层级关系,我们可以建立对应的图解模式:
算法(三):动态规划
即对于每一阶段(每一天)可以有三种选择——加班,正常上班,休息。
如果当前选择加班,则下一年只能休息,一次表示的图结构如上图所示。
这样问题就抽象成了经典的动态规划解法。
然后在编程实现就不难了。