转自:http://fuliang.javaeye.com/blog/151323
动态规划其实质上是通过开辟记录表,记录已求解过的结果,当再次需要求解的时候,可以直接到
那个记录表中去查找,从而避免重复计算子问题来达到降低时间复杂度的效果。实际上是一个空间
换时间的算法。动态规划,通常可以把指数级的复杂度降低到多项式级别。
一般算法书都会讲能不能用动态规划来求解问题,通常是判断有没有最有解结构,通常是通过“剪
切技术”来判断:即证明问题的一个最优解中,使用的子问题的解本身也必须是最优的。通常是假
设一个子问题不是最优的,那么找到一个最优的子问题来替换这个子问题,那么产生的最优解将优
于已找到的那个最优解,从而矛盾。
其实用不用动态规划来求解问题,还有一个关键是有没有重复的子问题。这也是使用动态规划
与贪心法的区别所在。。贪心法求解的问题也满足最优解结构,只是它能够在每一步都能够“贪婪的
”选出当前唯一的最优子问题,并且当前的选择,是不依赖以前的选择的,通过这种“贪婪的选择”
选到最后时,就得到了全局的最优解了,不会产生重复的子问题。而动态规划,在一步选择的时候,
是通过从以前求出的若干个与本步骤相关的子问题最优解中选择最好的那个,加上这一步的值,来构
造这一步那个子问题的最优解,而如果以前求出的若干个子问题不保存下来,就需要重新求(通常是递
归所致)。动态规划用武之地也无非是保存这些重复的子问题而避免重新求解而达到高效的目的。
动态规划的难点在于写出递推式。动态规划的步骤其实是很固定的,而每一个问题的递推式如何下手得到会因不同的问题而不同,这是个最关键的问题,没有通用的方法。通常是根据题目的问题,最终要求的问题,都会有几个数,以两个数M,N为例,然后让求最优值。你就可以使用v[M][N]数组来保存最有解,然后把问题替换成i,j两个数的问题,试图通过v[i][j]与前面求出来的解建立递推关系。建立递推关系后,你可以简单的写出递归形式的程序,这个程序只需要加上一条if(v[i][j]已求出) return v[i][j];就轻松改称了动态规划,这就是lookup的形式。当然如果已经有了递推式,你也很容易写出从底向上推的迭代形式。
一般的算法书讲的动态规划都是来求解最优解的问题,或许最初是用来求解规划问题的,而规划必然是最
优解问题,其实大多数的问题只要存在重复的子问题都可以使用动态规划的思路,就看你的重复的子问题
是不是多的值得使用空间来换时间这个思路了。