第3章 动态规划+LCS
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Step1: 分解问题,刻画最优解的结构
分解问题的经验:走一步看看
要确定是否为公共元素,必须进行比较操作。 不妨比较 X={x1,x2,…,xm}和Y={y1,y2,…,yn}的最后一个元素
Step1: 分解问题,刻画最优解的结构
原问题:从序列X={x1,x2,…,xm}和Y={y1,y2,…,yn}中找一最长公 共子序列Z={z1,z2,…,zk} 。 引入记号 Zk-1 ={z1,z2,…,zk-1}, Xm-1={x1,x2,…,xm-1}, Yn-1={y1,y2,…,yn-1}
c[i-1][j-1]
c[i-1][j] c[i][j]
围观我们要求的,c数组!!
y1 … …
c[i][j-1]
yn
c[0][n 1] c[0][n] c[0][0] c[0][1] x1 c[1][0] c[1][1] c[1][n 1] c[1][n] c c[m 1][n 1] c[m 1][n] xm c[ m][0] c[ m][1] c [ m ][ n 1] c [ m ][n]
(7,6)
CS(7,6)
x7=B≠y6=A (6,6) x6=y6=A (5,5)
(7,5) CS(6,6) CS(5,5)
CS(7,5)
CS(6,4)
x7=y5=B (6,4)
递归程序的雏形已经形成,成功就在彼岸!!???
(7,6)
子问题的进一步分解
x7=B≠y6=A
(6,6) x6=y6=A (5,5) x5=D≠y5=B (4,5) (5,4) x5=D≠ y4=A (4,4) (5,3) (7,5) x7=y5=B (6,4)
Z按照如下方式获得: (1)若xm=yn,令zk=xm=yn,则Zk-1是Xm-1和Yn-1的一个最长公共子序 列。 (2)若xm≠yn,则Z是 Xm-1与Y 或 X与Yn-1 的一个最长公共子序列。
原问题的分解示意图
(i,j):对应于处理以下数据的子问题
Xi={x1,x2,…,xi}, Yj={y1,y2,…,yj}
(m,n)
Zk=xm=yn
xm≠yn
(m-1,n-1)
(m-1,n) (m,n-1)
层层剥笋,子问 题逐渐变小! i=m,m-1,…,0 j=n,n-1,…,0
什么时候不用继续分解呢???
i=0 或 j=0
原问题的分解举例
1 2 3 4 5 A B C B D 1 2 3 B D C 4 5 A B 6 7 A B 6 A
X A B b C B D A B
Y i/ j 1 2 3 4 5 6 7
B D C 1 2 3 2 1 2 1 2 2 1 2 3 2 2 1 2 2 2 3 1 2 2 2 2
A B 4 5 1 2 3 2 2 1 2 3 1 2 1 2 2 1
A 6 1 3 2 3 2 1 2
构造出一个最优解
理解:Z中的元素在X中能依次被找到。
最长公共子序列
问题的理解
ห้องสมุดไป่ตู้
子序列 举例:Z={B,C,B,A}, X={A,B,C,B,D,A,B} Z中元素在X中所对应的的递增下标序列为 {2,3,4,6} 问: {B,B,C,A}是 X的子序列吗?
最长公共子序列
问题的理解
公共子序列: Z既是X的子序列,又是Y的子序列! Z={B,C,B,A}, X={A,B,C,B,D,A,B} {2,3,4,6} ≠ {1,3,5,6} Y={B,D,C,A,B ,A }
void LCS(int i,int j,char *x,int **b) //打印出Xi,Yj的一个最长公共子序列
{
if (i ==0 || j==0) return; if (b[i][j]== 1){ LCS(i-1,j-1,x,b); cout<<x[i]; } else if (b[i][j]== 2) LCS(i-1,j,x,b); else LCS(i,j-1,x,b); }
回顾
动态规划的求解步骤
分解问题,刻画最优解的结构
经验:考虑最后一步或者第一步
递归地定义最优值计算式 将子问题分层,以自底向上的方式计算出最优值 根据计算最优值时得到的信息,构造最优解
注:构造最优解需先求最优值!!
最长公共子序列
问题
给定2个序列X和Y,找出一个最长公共子序列。 X={x1,x2,…,xm} Y={y1,y2,…,yn}
第3章 动态规划 3.2 最长公共子序列
回顾
动态规划的思想
与分治法类似
原问题分解成若干个子问题 子问题的解合并得到原问题的解
与分治法不同:子问题往往不是互相独立的。 为了避免子问题的重复求解,将子问题划分至 多个层次,以自底向上的方式逐层求解,从而 获得最终结果。
回顾
两个基本要素
int i,j; //第0行,第0列 for (j = 0; j<= m; j++) c[0][j] = 0; for (i = 1; i <= n; i++) c[i][0] = 0; //下面逐行求解 for (i = 1; i <= m; i++) for (j = 1; j <= n; j++) { if (x[i]==y[j]) c[i][j]=c[i-1][j-1]+1; else if (c[i-1][j]>=c[i][j-1]) c[i][j]=c[i-1][j]; else c[i][j]=c[i][j-1]; }
小结
1 回顾动态规划
2 最长公共子序列问题的求解 (1)分解问题,得出最优解的结构特征 (2)递归定义最优值的计算式 (3)以自底向上的方式求得最优值 (4)构造最优解
思考
•对于最长公共子序列问题,如何证明其最优子结构性 质? •如何用程序求解最长公共子序列问题的一个最优解?
最优子结构性质
原问题:从序列X={x1,x2,…,xm}和Y={y1,y2,…,yn}中找一最长公共 子序列Z={z1,z2,…,zk} 。令 Zk-1 ={z1,z2,…,zk-1}, Xm-1={x1,x2,…,xm-1}, Yn-1={y1,y2,…,yn-1}, Z按照如下方式获得: (1)若xm=yn,令zk=xm=yn,则Zk-1是Xm-1和Yn-1的最长公共子序列 之一。 (2)若xm≠yn且zk≠xm,则Z是Xm-1和Y的最长公共子序列。 (3)若xm≠yn且zk≠yn,则Z是X和Yn-1的最长公共子序列。 由此可见,2个序列的最长公共子序列包含了这2个序列的前缀 的最长公共子序列。因此,最长公共子序列问题具有最优子结 构性质。
构造一个最优解
c[i-1][j-1]
1
c[i-1][j]
2
c[i][j-1]
3
c[i][j]
if (x[i]==y[j]) { c[i][j]=c[i-1][j-1]+1; b[i][j]=1;} else if (c[i-1][j]>=c[i][j-1]) { c[i][j]=c[i-1][j]; b[i][j]=2;} else { c[i][j]=c[i][j-1]; b[i][j]=3; } }
…
Step3:自底向上计算最优值
如何自底向上得到最优值? 问题分层 顶:c[m][n] 大i值,大j值 小i值,小j值 底:0行0列
c[i-1][j-1] c[i][j-1]
c[i-1][j] c[i][j]
c数组的值 i:行号;j:列号 (1)逐行求 (2)每行中自左往右求
自底向上求最优值举例
(6,6) x6=y6=A
(7,6) x7=B≠y6=A (7,5) x7=y5=B
i xi j yj
(5,5)
(6,4)
原问题和子问题相似,只是所涉及的序列不同。 直观感觉:直接使用递归程序实现该过程!!
void CS(int i,int j) /*该函数用于求子(i,j)问题的最优解 Xi={x1,x2,…,xi}, Yj={y1,y2,…,yj} */
问题的理解
子序列 公共子序列 最长公共子序列
最长公共子序列
问题的理解
子序列 定义: 称序列 Z={z1,z2,…,zk}为X={x1,x2,…,xm} 的子序列,是指存在一个严格递增下标序列
{i1 , i2 ,, ik }
z1
满足
zj
zk || x ik
|| || x i1 x i j
问题回顾:最长公共子序列
问题
给定2个序列X和Y,找出一个最长公共子序列。 X={x1,x2,…,xm} Y={y1,y2,…,yn} 最优解——最长公共子序列 最优值——最长公共子序列的长度
举例
X={A,B,C,B,D,A,B} Y={B,D,C,A,B,A} m=7 n=6
找 {B,C,A,B}, {B,C, B,A}……中的一个序列 最优值为4
A B 4 5 0 1 1 2 2 2 3 3 0 1 2 2 3 3 3 4
A 6 0 1 2 2 3 3 4 4
该计算过程如何用 程序实现呢?
A B c C B D A B
void LCSLength (int m,int n,char *x,char *y,int **c) { //该函数用于求长度分别为m,n的序列X与Y的最 长公共子序列
}
Step4:构造一个最优解
X A B c C B D A B Y B D C i/ j 0 1 2 3 0 1 2 3 4 5 6 7 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 1 1 1 2 2 2 0 0 1 2 2 2 2 2 A B 4 5 0 1 1 2 2 2 3 3 0 1 2 2 3 3 3 4 A 6 0 1 2 2 3 3 4 4
子问题重叠!! 递归实现会重复计算(5,3) 老实按动态规划继续吧!
x6=y4=A
(5,3)
喔喔,又出现 (5,3)了哦!
回顾动态规划
问题分解+最优解(最长公共子序列)结构 接下来 最优值(最长公共子序列的长度)之间的关系 自底向上求出最优值 之后:再想办法构造一个最优解
Step2: 递归定义最优值
最优子结构性质 原问题的最优解包含子问题的最优解
矩阵连乘 A1…A6的最优计算次序 (A1(A2A3))((A4A5)A6) 包含 A1…A3 A4…A6 等子问题的最优计算次序
重叠的子问题
子问题之间共享了一些更小规模的子问题 递归算法求解时,子问题的求解过程间相互独立,所 共享的更小规模子问题被反复计算
X={A,B,C,B,D,A,B}
Y={B,D, C,A,B,A}
m=7 n=6 最终目标:c[m][n]=4
例的结果
c[i-1][j-1] c[i][j-1] c[i-1][j]
X
c[i][j]
Y B D C i/ j 0 1 2 3 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 1 1 1 2 2 2 0 0 1 2 2 2 2 2 1 2 3 4 5 6 7
最长公共子序列
问题的理解
最长公共子序列:最长的公共子序列! X={A,B,C,B,D,A,B} Y={B,D,C,A,B,A} 它们的公共子序列有: 长度为1的:{A},{B}, {C} ,{D} 长度为2的: {A,A}, {A,B}, {B,A} ,{B,B} …… 长度为3的: {A,B,A}, {B,B,A}, {B, A,B}…… 长度为4的: {B,C,A,B}, {B,C, B,A}…… 那么,还有长度为5的吗????
c[i][j]:子问题(i,j)的最优值 Xi={x1,x2,…,xi}, Yj={y1,y2,…,yj} c[m][n]即为原问题的最优值
(m,n)
Zk=xm=yn
xm≠yn (m-1,n) (m,n-1)
(m-1,n-1)
c[m 1][n 1] 1 xm yn c[m][n] max{c[m][n 1], c[m 1][n]} xm yn
什么情况不用这样绕迷宫呢???
m=0 或 n=0
Step2: 递归定义最优值
c[i][j]:子问题的(i,j)的最优值 Xi={x1,x2,…,xi}, Yj={y1,y2,…,yj} i=m,…,0 j=n,…,0
0 c[i ][ j ] c[i 1][ j 1] 1 max{c[i ][ j 1], c[i 1][ j ]} i 0或j 0 i, j 0; xi y j i, j 0; xi y j