1 动态规划问题
动态规划算法和分治法类似,都是将带求解问题分解为若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的答案。与分治法不同的是,动态规划要用一个表来记录所有已解决的子问题的答案。不管该问题是否以后会被用到,只要它被计算过,就将其结果填入表中。在需要时从表中找出答案,避免大量重复计算,从而得到多项式时间算法。通常按一下几个步骤设计动态规划算法:
(1)找出最优解性质,刻画最优解结构;
(2)递归的定义最优值;
(3)以自底向上的方式计算最优值;
(4)根据计算最优值得到的信息,构造最优解。
具体实例有:矩阵连乘,最长公共子序列,流水调度作业,0-1背包问题,最优二叉搜索树等。
2 最长公共子序列
2.1 原理
问题描述:给定两个序列 X = { x1, x2, …, xm }和Y = { y1, y2, …, yn },找出X和Y的最长公共子序列。
最优解:最长公共子序列的长度 m[ i ][ j ]以及相应的位置b[ i ][ j ]。
递归定义最优值:
第一种情况:当 i = 0,或者 j = 0 时,长度为 0;
第二种情况:当 xi = yi 时,表示长度等于子序列(去掉 i 位置元素后的序列)+1, 1 表示xi(或者 yi );b[ i ][ j ] = 1
第三种情况:当 xi != yi 时,表示两个不同子序列公共长度的最大值。 b[ i ][ j ]=2,b[ i ][ j ]=3
2.2 时间复杂度和空间复杂度
时间复杂度: 需要计算每个 c[ i ][ j ]的大小,所以时间为 mn;
空间复杂度: 需要存储c[ i ][ j ],所以空间为 mn。
2.3 python代码
#coding:utf-8
def LCS(i,j,X,b,out): #得到最长子序列
if i == -1 or j == -1:
return
if b[i][j] == 1:
print i,j
out.append(X[i])
LCS(i-1,j-1,X,b,out)
elif b[i][j] == 2:
LCS(i-