算法设计方法-动态规划

     前面介绍了一个比较常用的算法设计技术,分治法,当碰到一个实际的问题时,看能够利用分治法解决,分治法适应于解决子问题独立且不重叠的,但是如果子问题出现重叠就不利用分治法了。这里介绍另外一种算法设计方法,动态规划,这种算法设计方法虽然基本思想和分治法很相似,划分子问题,通过子问题解决更高层的问题。但是两者明显的区别在于动态规划划分的子问题具有重叠的性质(不过独立性还是要保证的),而且一般用于解决最优化的问题~

    动态规划算法的解决步骤:

1、我认为首先比较重要的还是正确的抽象化问题,然后得到问题的最优子结构。有一部分题目的描述方式完全是文字化的描述,这时就先抽象出其中的数学结构,然后根据数学结构得出问题的最优子结构,

2、根据第一步中抽象出的公式化描述和最有子结构,可以简单正确的写出最有子结构的递推式。但是如果第一步中抽象化方法不完美很难写出递推式的,书中的问题很多都是抽象出好数学结构了,所以我认为还是要多加联系数学化一个问题的表达,

3、根据第二步的递推式自底向上进行计算得出最优解。因为动态规划的一个特征是具有重叠子问题,虽然递归的程序实现可以帮助程序容易实现,但是这里如果利用递归,需要重复解决子问题,时间复杂度可能仍是指数级的,后面会介绍一个记账法,帮助解决重复计算,不过还是建议自底向上计算,

4、这个一般是可选步骤,到第三步已经得出最优解了,但是如果要构造出最优解,必定要在算法执行过程中相应的做一些记录,这样第四步就是利用这些记录来构造出一个最优解的具体解决方案。

    发现最优子结构的方法:

1、做一个选择将问题分割为一个或者多个子问题,这里是试探的随便选择

2、接着假设你的这个选择就是一个最优的选择

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

4、利用一种“剪贴”技术,证明在问题的一个最优解中,使用的子问题的解本身也必须是最优的。

    描述子问题空间可以遵循一个经验规则,尽量保持这个空间简单,然后在需要时扩充它。

上面有些描述很难理解,最优子结构的发现方法摘自算法导论,我仍没能理解子问题空间这个概念,接下来还是通过具体的例子自己领悟一下其中的道理。

第一个装配线问题,问题描述如上图,根据题目可以看到题目已经抽象化了,接下来只需要针对问题找出最优子结构,然后写出递归式,有了递归式就可以完成伪代码,伪代码到代码的转换整个流程就非常的流畅了。

首先考虑最快的方案必定是第一条线的结尾S1,n+x1和S2,n+x2取小的值,及为最快的值。所以问题转换为求到达S1,n和S2,n的最小值,这里分解问题,将问题规模缩小可以看到到达S1,n经过了S1,n-1或者S2,n-1,但是这里的任何n的S1,n都是最短路径,如果S1,n-1不是最短的,利用剪切的技术,必定存在另外一个更短的S1,n-1路径替换S1,n-1,所以能够S1,n更短,但是S1,n已经是最短的了,所以S1,n-1最快的路径,所以这里最优子结构已经找出,接下来是递归式,根据上面的总结写出递归式也不是太难:

根据以上结构伪代码也比较简单的实现:

代码执行结束之后的数据记录:

这里为了还原出最快路径,l是必须保存的,而且不能省略,但是这里的f的中间记录可以节省一些空间,因为计算某位的时候只用到前一位,所以只需要常数的存储空间即可。其实后面很多都是可以节省一部分存储空间的,但是一般算法的设计考虑的是时间效率,空间考虑比较少,甚至不考虑。

还原路径:

递归的正确方向还原路径:

PRINT-STATIONS(l,j,n)
    i = l*
    if j=0
        return
    else
        if(j>1) i=li[j]
    PRINT-STATIONS(l,j-1,n)
    if j=n
        i=l*
        print i
    else
        i=li[j+1]
        print i
    
    

 第二个问题是矩阵链乘积结合问题

矩阵相乘时间复杂度计算

 

动态规划的3个解决问题的步骤:

     

伪代码如下:

这个存储结构书中经常把矩阵结构反转,我个人认为反转反而不利于理解,所以还是利用正常的正方形矩阵解释

一个是最优解的计算,一个是还原最优解需要记录的分裂的k值~!

还原括号添加方法的伪代码

动态规划算法时间复杂度影响因素:

上面两个的分析可以参照这两个因素:

接下来分析一下重叠子问题的影响:举例为矩阵链相乘的例子

 

 所以就产生了下面的记账的方法...

伪代码如下:

方法的适用范围:

有种要吐血的感觉,这篇博文写出来肯定效果不是太好,内容太多了,而且好多都是直接从可见里copy过来的,即使这样内容都这么多,动态规划呀,干嘛讲这么多内容,这里全是讲的原理,有空的时候应该实现一下这些算法的,不过这些都是后话了,接下来还有两个动态规划的问题,最长公共子序列和最优二叉查找树...

 

最长公共子序列

问题描述

 最长子序列步骤

最优二叉查找树

算法的设计思想之一,掌握思想即可。

posted @ 2012-12-25 17:19  weixliu  阅读(...)  评论(...编辑  收藏