zoukankan      html  css  js  c++  java
  • 动态规划基本思想

     

     动态规划与贪心策略类似,将一个问题的解决方案视为一系列决策的结果。不同的是,贪心算法每采用一次贪心选择便做出一个不可撤回的决策,而在动态规划中,还要考察每个最优决策序列中是否包含一个最优决策自序列。使用动态规划时,所求问题应具有以下两种性质。

     

      1.最优子结构性质

     

      所求问题的最优子结构性质是采用动态规划算法的条件之一,这种性质又被称为最优化原理。动态规划方法采用最优化原理来建立用于计算最优解的递归式。所谓最优化原理即不管前面的策略如何,此后的决策必须是基于当前状态(由上一次决策产生)的最优决策。由于对于有些问题的某些递归式来说并不一定能保证最优原则,因此在求解问题时有必要对它进行验证。若不能保持最优原则,则不可应用动态规划方法。在得到最优解的递归式之后,需要执行回溯以构造最优解。当最优决策序列中包含最优决策子序列时,可建立动态规划递归方程,它可以帮助我们高效地解决问题。

     

      2.子结构重迭性质(重叠子问题

     

      人们总希望编写一个简单的递归程序来求解动态规划递归方程。然而,如果不努力地去避免重复计算,递归程序的复杂性将非常可观。如果在递归程序设计中解决了重复计算问题,复杂性将大幅度下降。这种方法的思想是:由程序设置“备忘录”,每计算出一个新的子结构的解时,都保存起来。当遇到一次递归时,判断是否已经计算,如果已经计算,只需取出先前保存的结果既可。动态规划递归方程也可用迭代方式来求解,这时很自然地避免了重复计算。尽管迭代程序与避免重复计算的递归程序有相同的复杂性,但迭代程序不需要附加的递归栈空间,因此将比避免重复计算的递归程序更快。

     动态规划其实质上是通过开辟记录表,记录已求解过的结果,当再次需要求解的时候,可以直接到那个记录表中去查找,从而避免重复计算子问题来达到降低时间复杂度的效果。实际上是一个空间换时间的算法。动态规划,通常可以把指数级的复杂度降低到多项式级别。 一般算法书都会讲能不能用动态规划来求解问题,通常是判断有没有最优子结构,通常是通过“剪切技术”来判断:即证明问题的一个最优解中,使用的子问题的解本身也必须是最优的。通常是假设一个子问题不是最优的,那么找到一个最优的子问题来替换这个子问题,那么产生的最优解将优于已找到的那个最优解,从而矛盾。


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

    附:

      利用动态规划求解最优问题的步骤:
        (1)证明该问题具有最优子结构性质;
        (2)根据最优子结构性质,写出最优值的递归表达式;
        (3)根据递归式,说明该问题具有重叠子结构性质;
        (4)采用自底向上的方式计算,写出求解最优值的非递归算法,同时构造最优解的解空间树;
        (5)遍历解空间树,求得最优解。

     

      利用贪心算法求解最优问题的步骤:
        
     (1)选定合适的贪心选择的标准;
        (2)证明在此标准下该问题具有贪心选择性质;
        (3)证明该问题具有最优子结构性质;
        (4)根据贪心选择的标准,写出贪心选择的算法,求得最优解。

  • 相关阅读:
    Codeforces Round #592 (Div. 2)C. The Football Season(暴力,循环节)
    Educational Codeforces Round 72 (Rated for Div. 2)D. Coloring Edges(想法)
    扩展KMP
    poj 1699 Best Sequence(dfs)
    KMP(思路分析)
    poj 1950 Dessert(dfs)
    poj 3278 Catch That Cow(BFS)
    素数环(回溯)
    sort与qsort
    poj 1952 buy low buy lower(DP)
  • 原文地址:https://www.cnblogs.com/youxin/p/2458584.html
Copyright © 2011-2022 走看看