dp入门之LCS (最长公共子序列) LIS(最长上升子序列)数塔问题

LCS:最长公共子序列

就是说给你两个序列x={x1,x2,x3……,xm}和y={y1,y2,y3,……,ym}找出x和y的一个最长的公共子序列。

思路:如果是暴力枚举则为枚举x序列的所有子序列,检查每个子序列是否也是y的子序列,记录找到最长的公共子序列,共有2^m种情况,暴力枚举的时间复杂度为指数阶.时间复杂度特别高,在m比较小时可以直接枚举,但如果很大时,会超时。

所以想到了动态规划,看了好几本书对这个动态规划方程的推导讲解,但看不是很懂,趣学算法里面是拿反证法推导的,感觉比较明了易懂。

分析:假设已经知道Zk是xm和yn的最长公共子序列。

1.若xm=yn=zk,则Zk-1是Xm-1和Yn-1的最长公共子序列。

反证法证明若Zk-1不是最长公共子序列,则设M为Xm-1和Yn-1的最长公共子序列,M的长度大于Zk-1的长度,M>Zk-1,Xm-1和Yn-

1的后面添加一个相同的字符Xm=Yn,则M+{Zk}>Zk-1+{Zk}=|Zk|,那么Zk不是Xm和Yn的最长公共子序列,这与假设不符。

2,若xm!=yn&&xm!=zk,我们可以把Xm去掉,那么Zk是Xm-1和Yn的最长公共子序列。

反证法证明若Zk不是最长公共子序列,则设M为Xm-1和Yn的最长公共子序列,M的长度大于Zk的长度,M>Zk,Xm-1和Yn的后面添加一个字符Xm,则M也是Xm和Yn的最长公共子序列,因为M>Zk,那么Zk不是Xm-1和Yn的最长公共子序列,这与假设不符。问题得证。

3.若xm!=yn&&yn!=zk,我们可以把Yn-1去掉,那么Zk是Xm和Yn-1的最长公共子序列。

反证法证明若Zk不是最长公共子序列,则设M为Xm和Yn-1的最长公共子序列,M的长度大于Zk的长度,M>Zk,Xm和Yn-1的后面添加一个字符Yn,则M也是Xm和Yn的最长公共子序列,因为M>Zk,那么Zk不是Xm和Yn-1的最长公共子序列,这与假设不符。问题得证。

根据以上推理,设C[i][j]表示Xi和Yj的最长公共子序列长度,若Xm=Yn=Zk,那么C[i][j]=C[i-1][j-1]+1;

若Xm!=Yn;那么我们只需要求解Xi和Yj-1的最长公共子序列和Xi-1和Yj-1的最长公共子序列,比较它们的长度哪一个更大,就取哪一个值。即C[i][j]=max{C[i][j-1],C[i-1][j]}则递归方程为:

c[i][j]=0,(i=0||j=0)   c[i][j]=c[i-1][j-1]+1(i,j>0&&xi==yj)  c[i][j]=max{c[i][j-1],c[i-1][j]};

LIS:最长上升子序列问题。

给定n个整数A1,A2,A3……Am,按照从左到右的顺序选出尽量多的整数,组成一个上升子序列,子序列可以理解为:删除0个或多个数,其他顺序不变,例如:1,6,2,3,7,5.可以选出1,2,3,5也可以选出1,6,7.但是前者更长,选出的子序列中相邻元素不相等。子序列是指不一定连续但先后顺序一致的n个数字或字符,即可以去掉字符串或者一串数字的部分字符,但不改变先后顺序。

求解方法:化简为子问题,求前n个数的最长上升子序列。

2,7,1,5,6,4,3,8,9。

d(i)(i属于[1,n])来表示前i个数以a[i]结尾的最长上升子序列。

前一个数  d(1)=1  子序列为2

前二个数  d(2)=d(1)+1  子序列为2,7

前三个数  d(3)=1  子序列为1

前四个数  d(4)=d(3)+1  子序列为2,5

前五个数  d(5)=d(4)+1  子序列为2,5,6

前六个数  d(6)=d(1)+1  子序列为2,4

前七个数 d(7)=d(1)+1   子序列为2,3

前八个数  d(8)=d(5)+1  子序列为2,5,6,8

前九个数  d(9)=d(8)+1 子序列为2,5,6,8,9

d(i)=max{d(1),d(2),d(3)……d(i)}  LIS  d(9)=5;

dp[i]=max{dp[j]+1,dp[i]};

边界处理  dp[i]=1(1<=i<=n)

注意分治和动规的区别,分治算法是把原问题分解为若干子问题,自顶向下求解各子问题,合并子问题的解,从而得到原问题的解,这就不可避免的出现很多重复的运算,动规是也是把原问题分解为若干子问题,但是动规是自底向上,先求解最小的子问题,把结果存储在表格中,再求解大的子问题时,直接从表格中查找子问题的解,避免重复计算,提高了效率。

求解动态规划问题的常用方法:

1.模型匹配法,例如数塔模型,线性dp,最长上升子序列,最长公共子序列,最大子序列和等。

2.三要素法:仔细分析尝试着确定动态规划三要素,不同问题确定方向不同:

    先确定阶段的问题:数塔问题

    先确定状态的问题:大多数都是先确定状态的。

    先确定决策的问题:背包问题

3.寻找规律法:耐心推几组数据,看规律,找规律间的共性,有点贪心的意思。

4.边界条件法:找到问题的边界条件考虑边界条件和他的邻接状态之间的关系。

另一个经典模型

数字三角形问题:非负整数组成的三角形,第一行只有一个数,除了最下行之外每个数的左下方和右下方各有一个数,从第一行的数开始,每次可以往左下或者右下走一格,知道走到最下行,把沿途经过的数全部加起来,如何才能使得这个和尽量大?

回溯法分析:动态的决策问题,每次有两种选择——左下和右下,一个n层数字三角形的完整路线有2^n-1条,当n很大时回溯法的速度会特别慢。

把当前的位置(i,j)看成一个状态,然后定义状态(i,j)的指标函数d(i,j)为从格子(i,j)出发时能得到的最大和,不同状态之间是如何转移的?从格子(i,j)出发有两种决策,如果往左走,则走到(i+1,j)后需要求从(i+1,j)出发后能得到的最大和这一问题,

如果往右走,则走到(i+1,j+1)后需要求从(i+1,j+1)出发后能得到的最大和这一问题,由于在这两个决策中自由选择,所以应选择d(i+1,j)和d(i+1,j+1)中较大的一个。

所以状态转移方程为:d(i,j)=a(i,j)+max{d(i+1,j),d(i+1,j+1)}.

猜你喜欢

转载自blog.csdn.net/cjh1459463496/article/details/88856008