动态规划同样是一种将问题分解为求解子问题的方法,不过与分治不同的是,动态规划算法的子问题不是相互独立的,而是有公共的部分,即有重叠子问题,这个时候使用分治算法,将会重复计算公共的子问题,效率很低!而用某种方法将中间计算的结果保存下来,以供后面直接使用,将会大大提高效率,体现了一种“用空间换时间的”思想!
那么什么样的问题才可以使用动态规划方法呢?有两个条件:
动态规划算法的设计步骤:
接下来,将通过几个例子来体会动态规划的基本思想。
例1: 最长公共子序列问题
思考,该问题的优化子结构是:
证明如下:
递归的定义最优解的代价:
重叠子问题:
建立递归方程:
则从左往右、从上往下进行计算:
写出算法的伪代码如下:
构造最优解:
例2: 矩阵链乘法
注意到,矩阵链乘法的代价对于不同的计算顺序,代价也不同。
优化子结构:
重叠子问题:
递归的定义最优解的代价:
自底向上的计算最优解的代价:
算法的伪代码如下:
构造最优解:
算法的时间复杂度与空间复杂度分析:
例3: 0/1背包问题
思考 :
优化子结构:
重叠子问题:
建立递归方程:
自底向上的计算最优解的代价:
算法的伪代码如下:
构造优化解:
算法复杂度分析:
例4: 最优的二叉搜索树
先来看下二叉搜索树的相关概念:(可以参考:二叉搜索树)
问题的定义:
思考 :该问题怎么去划分子问题?是否具有优化子结构呢?
优化子结构:
建立递归方程:
所以:
自下而上的计算优化解的搜索代价:
算法伪代码如下:
其中:
算法的复杂度分析:
参考资源:
【1】哈工大骆吉洲《算法分析与设计》PPT