动态规划算法

    动态规划算法通常用于求解具有某种最优性质的问题。在数学与计算机科学领域,动态规划用于解决那些可分解为重复子问题(overlapping subproblems,想想递归求阶乘吧)并具有最优子结构(optimal substructure,想想最短路径算法)的问题,动态规划比通常算法花费更少时间。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值的解。动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次。如果我们能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间。我们可以用一个表来记录所有已解的子问题的答案。不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中。这就是动态规划法的基本思路。具体的动态规划算法多种多样,但它们具有相同的填表格式。

    动态规划的应用十分广泛,如最大子序列和、最优二叉查找树、斐波那契数列等等。

  • 应用举例:
    1.  最大子序列和
         这里转载两篇不错的文章:

         最大子序列和问题

         动态规划法-------最大连续子序列和

    2.  斐波那契数列

         寻找Fibonacci序列中第n个数,基于其数学定义的直接实现:

         function fib(n)
             if n = 0 
                 return 0
         else if n = 1
             return 1
         return fib(n-1) + fib(n-2)

        如果我们调用fib(5),将产生一棵对于同一值重复计算多次的调用树:

           fib(5)
           fib(4) + fib(3)
           (fib(3) + fib(2)) + (fib(2) + fib(1))
           ((fib(2) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))
           (((fib(1) + fib(0)) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))

    特别是,fib(2)计算了3次。在更大规模的例子中,还有更多fib的值被重复计算,将消耗指数级时间。

    现在,假设我们有一个简单的映射(map)对象m,为每一个计算过的fib及其返回值建立映射,修改上面的函数fib,使用并不断更新m。新的函数将只需O(n)的时间,而非指数时间:

   var m := map(0 → 1, 1 → 1)
   function fib(n)
       if map m does not contain key n
           m[n] := fib(n-1) + fib(n-2)
       return m[n]

    这一保存已计算出的数值的技术即被称为缓存,这儿使用的是自顶向下的方法:先将问题划分为若干子问题,然后计算和存储值。

    在自下而上的方法中,我们先计算较小的fib,然后基于其计算更大的fib。这种方法也只花费线性(O(n))时间,因为它包含一个n-1次的循环。然而,这一方法只需要常数(O(1))的空间,相反,自顶向下的方法则需要O(n)的空间来储存映射关系。

   function fib(n)
       var previousFib := 0, currentFib := 1
       if n = 0 
           return 0
       else if n = 1
           return 1
       repeat n-1 times
           var newFib := previousFib + currentFib
           previousFib := currentFib
           currentFib  := newFib
       return currentFib

在这两个例子,我们都只计算fib(2)一次,然后用它来计算fib(3)和fib(4),而不是每次都重新计算。

    3. 货币找零问题

    见:货币找零问题

    未完待续...

posted on 2011-05-01 13:27  Kadin Zhu  阅读(465)  评论(0编辑  收藏  举报