动态规划

     最近看算法导论动态规划这节,有些感触和不解的地方,在此记录下来。

     动态规划是一种解决问题的方法,其思想是将这一问题划分为不同的互相联系的阶段,并且在每一阶段进行决策,使得整个问题具有最优的解。

     适合动态规划的问题是有条件的,其必须满足:

    1)最优化原理         即将这一问题划分为不同阶段(按序排列,例如0,1,2,...,n),并进行决策,如果能够使整个问题具有最优解,那么对其中某一阶段k而言,其所做的决 策是最优的,也就是说一个最优化决策的子策略也是(总是)最优的;

     2)无后效性            即对于某一给定阶段的状态,它之前各阶段的状态无法直接影响它未来阶段的决策,而只能通过当前当前这个状态。每个阶段的状态都是过去历史的一个 完整总结(只要当前状态确定,它之前的状态也就已经确定)

     3)有重叠子问题    即各个子问题之间相互联系,某子问题需要借助其之前的子问题进行求解

     动态规划与分治法的联系与区别:

     联系:它们都是将某一过程(问题)划分为不同的阶段(子问题)

     区别:分治法要求各子问题是相互独立的,即各子问题分别求之,互不影响,最后将各子问题的解组合即可;

动态规划要求各子问题是互相联系的,其中某一子问题是通过其前一子问题的解再进行决策而解出的。

    

     动态规划是一种多阶段决策过程,即将过程划分阶段:   阶段1、阶段2、阶段3、...、阶段n  ,每一阶段具有某一状态(最优),对其进行决策将产生后一阶段的状态。

决策,是前后状态之间的桥梁。状态,各阶段所处的客观情况,如时间、长度、次数、价值等等用以标识某一问题的最优解。用表存放各个阶段状态。

     动态规划解决某一问题时,重在其分析的过程,那么它是如何解决问题的呢?其步骤为:

     1)正确理解原问题                            理解各个关键信息,即输入哪些数据;分析原问题是什么,即描述该问题的最优解(状态是什么,即用二维数组怎么表示)

     2)将问题划分为一系列的阶段        这里只需要去分析中间某一阶段,其状态怎么表示,其前一阶段是什么,状态如何,这两个相邻阶段之间有何关系

     3)根据2)的分析,写出递推式      这个递推式是中间某一阶段的状态怎么用其之前一阶段的状态再进行怎样的决策推导出来,又称状态转移方程,考虑边界问题!

     4)根据递推式,写出代码                即照着递推式填表(填数组矩阵),该表又称为最优决策表,其行为决策的阶段,其列为?(有的说为问题的状态,我还没想好),表里 的数据是各个阶段时问题的最优值。怎么获得问题的最优解呢?最优解存放于表中某一位置处,之间访问即可

      注:算法导论上说第一步为描述最优解的结构,也就是寻找最优的子结构,然后利用这一子结构,就可以根据子问题的最优解构造出原问题的一个最优解。我想它体现在上面前两个步骤的分析过程。

      从这个步骤中也可以看出动态规划的三个要素: 1)问题的阶段           2)每个阶段的状态                3)从前一阶段转化到后一阶段之间的递推关系

       我感觉最难的地方在于分析递推式,只要递推式写出来了,问题也就解出来了。

       

      关于动态规划的复杂度

       还是再想一下动态规划所采取的基本方法:经常会遇到复杂问题不能简单地分解成几个子问题,而是一系列的子问题,简单地采用把大问题分解成子问题,并综合子问题的解导出大问题的解,这种方法(即递归的去解)会按问题的规模呈幂级数增加,为了节约重复求相同子问题的时间,引入一个数组,不管它们是否对最终解有用,把所有子问题的解存放该数组中,当获取最优解时,进行访问该表即可。

        也就是说,动态规划采用的是以空间换时间方法,也就是说按普通方法求解时(枚举、递归),则需要指数级的时间复杂度,而动态规划只需要多项式的时间复杂度(如n^3)。

一个动态规划算法的运行时间依赖于两个因素的乘积:子问题的总个数和每个子问题有多少种选择,即for循环的规模

       关于时间复杂度的优化方法,看这个博客http://blog.csdn.net/zdl1016/article/details/4659305

       空间复杂度的优化:   优化空间复杂度依赖于递推式,因为递推式影响了1)填数组矩阵的顺序 2)空间复杂度的优化     即:

        1)填矩阵时你的顺序要:确保每填一个新的位置时,所用到的那些位置的数据已经填好。

        2)空间优化: 当一个位置在以后还有用的时候你不能覆盖它。

       空间复杂度的优化,就是节省空间(往往表中有大量重复出现的值,避免存储这些值,将其丢掉),根据填矩阵时的顺序来进行优化的,有时可将二维数组用一个一位数组替代即可(如0-1背包问题)。


       算法导论上关于动态规划的基础--------------------最优子结构和重叠子问题                 

       1. 最优子结构

        什么是最优子结构:如果问题的一个最优解中包含子问题的最优解,则该问题就具有最优子结构。

        最优子结构有什么用: 当一个问题具有最优子结构时,提示我们动态规划可能会适用(在这种情况下,贪心策略可能也是适用的)。利用子问题的最优解来构造问题的一   个最优解。

        如何找最优子结构:

        1) 问题的一个解可以是做一个选择。做这种选择会得到一个或多个有待解决的子问题

        2) 假设对一个给定的问题,已知的是一个可以导致最优解的选择。不必关心如何确定这个选择,尽管嘉定它是已知的

        3) 在已知这个选择后,要确定哪些子问题会随之发生,以及如何最好地描述所得到的子问题的空间

        4) 利用“剪贴”技术,证明在问题的一个最优解中,使用的子问题的解 本身也必须是最优的,即通过假设不是最优解,然后导出矛盾,即可证明

        动态规划以自底向上的方式来利用最优子结构。即首先找到子问题的最优解,解子问题,然后找到问题的一个最优解。如何找问题的一个最优解?需要在子问题中做出选择,即选择将用哪一个来求解问题。注:贪心算法是以自顶向下的方式使用最优子结构,以后看的时候去理解。

        2. 重叠子问题

        什么是重叠子问题:当一个递归算法不断地调用同一问题时,即反复地解之前解过的问题,就说该最优问题包含重叠子问题。

        重叠子问题有什么用:动态规划算法总是充分利用重叠子问题,即通过每个子问题只解一次,把解保存在一个在需要时就可以查看的表中,下次用到这个解时,只需要看表

        为了充分利用重叠子问题性质,出现一种动态规划的变形:做备忘录。备忘录既具有通常的动态规划方法的效率,又采用一种自顶向下的策略。

        做备忘录:在填表时采用递归算法为每一个子问题的解在表中记录一个表项。方法为:开始时每个表项最初包含一个特殊值,以表示该表项有待填入,当在递归算法的执行中第一次用到一个子问题时,就计算它的解并填入表中,以后再遇到时只要查看并返回表中先前填入的值即可。由于引入了递归,所以需要额外的一个常数因子代价(递归代价以及维护表格的开销)。

 

         有很多动态规划方面的问题,接下来要针对不同的问题更加深入的理解动态规划这个方法。

        

    

                                                      

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值