•动态规划算法的设计步骤
–分析优化解的结构
–递归地定义最优解的代价
–自底向上地计算优化解的代价保存之,并获取构造最优解的信息
–根据构造最优解的信息构造优化解
•使用Dynamic Programming的条件
–
Optimal substructure
(优化子结构)
•当一个问题的优化解包含了子问题的优化解时,我们说这个问题具有优化子结构。
•缩小子问题集合,只需那些优化问题中包含的子问题,减低实现复杂性
•优化子结构使得我们能自下而上地完成求解过程
–
Subteties
(重叠子问题)
•在问题的求解过程中,很多子问题的解将被多次使用
最长公共子序列(Longest Common Susequence)
公共子序列
–Z是序列X与Y的公共子序列,如果Z是X的子序也是Y的子序列。
最长公共子序列(LCS)问题
输入:X = (x1,x2,...,xn),Y = (y1,y2,...ym)
输出:Z = X与Y的最长公共子序列
X和Y的LCS的优化解结构为
子问题重叠性
递归方程
•计算LCS长度的算法
–
数据结构
C[0:m,0:n]:C[i,j]是Xi与Yj的LCS的长度
B[1:m,1:n]:B[i,j]是指针,指向计算C[i,j]时所选择的子问题的优化解所对应的C表的表项
打印最长子序列
•基本思想
–
从
B[m, n]
开始按指针搜索
–
若
B[
i
, j]=
“
↖
”
,
则
x
i
=
y
j
是
LCS
的一个元素
–
如此找到的
“
LCS
”
是
X
与
Y
的
LCS
的
Inverse
Print-LCS(B, X,i, j)
IF i=0 or j=0 THEN Return;
IF B[i, j]=“↖”
THEN Print-LCS(B, X, i-1, j-1); Print xi;
ELSE If B[i, j]=“↑”
THEN Print-LCS(B, X, i-1, j);
ELSE Print-LCS(B, X, i, j-1).
问题描述
•输入:<A1, A2, ..., An>, Ai是矩阵
•输出:计算A1´A2´...´An的最小代价方法
问题特征
–矩阵乘法满足结合率。
–计算一个矩阵链的乘法可有多种方法:
–不同计算顺序有不同的代价
矩阵链乘法优化问题的解空间
–设p(n)=计算n个矩阵乘积的方法数
–p(n)的递归方程
优化解的结构
–若计算A1~n的优化顺序在k处断开矩阵链, 即A1~n=A1~kXAk+1~n,则在A1~n的优化顺序中,对应于子问题A1~k的解必须是A1-k的优化解,对应于子问题Ak+1~n的解必须是Ak+1~n的优化解。
考虑到所有的k,优化解的代价方程为
m[i, j] =计算Ai ~j的最小乘法数
子问题重叠性
算法伪代码:
算法复杂性分析
•时间复杂性
–
计算代价的时间
•
(l,
i
, k)
三层循环
,
每层至多
n-1
步
•
O(n
3
)
–
构造最优解的时间
:
O(n)
–
总时间复杂性为:
O(n
3
)
•空降复杂性
–
使用数组
m
和
S
–
需要空间
O(n
2
)