LIS 最长递增子序列 点击此处看作者参考的博客
定义:从一个序列中选出一段长度最长可以不连续的且一定递增的子序列
例如 A 4 5 7 1 3 9
最长子序列为 4 5 7 9
定义dp[i]为:从左至右 从序列A中选定 最后一位为A[i]的 子序列,在这些子序列中,连续递增区间最大的值
我们先用人脑自然的方法去写出每一位数对应的dp[i]
- dp[1]=1;
- dp[2]=2;
- dp[3]=3;
- dp[4]=1;
- dp[5]=2; //1 3
- dp[6]=4; //4 5 7 9
其实我们用的人脑自然的方法就是选择性的忽略掉那么不递增的数字
我们一步步分析得出状态转移方程
第一部分:
就拿dp[4]来说,为什么它会变成1;
最后一位为A[4],就是最后一个数字为1;
看下有哪些满足定义的序列
1.st 4 1
2.nd. 5 1
3.rd 7 1
4.th 4 5 1
5.th 4 7 1
6.th 5 7 1
7.th 4 5 7 1
显然这些子序列的最大连续递增区间为1
为什么?因为A[4]比 序列A[i](i<=3)都要小所以A[4]=1;
现在开始放代码部分
#include<iostream>
using namespace std;
int A[10]={0,4,5,7,1,3,9};
int dp[10];
int findout()
{
for(int i=1;i<=6;i++)
{
dp[i]=1;
for(int j=1;j<i;j++)
{
if(A[i]>A[j]&&dp[j]>=dp[i])
dp[i]=dp[j]+1;
}
}
int ans=-1;
for(int i=1;i<=6;i++)
ans=max(ans,dp[i]);
return ans;
}
int main()
{
cout<<findout()<<endl;
return 0;
}
第二部分:
我们计算dp[i]的时候,只需要在j(1~i-1)的范围内找 到满足条件A[i]>A[j]时 找到dp[1~i-1]中最大的作为dp[j]即可
如果A[i]>A[j]但是dp[j]<dp[i]说明 A[j]这一段中存在断层(即连续递增终止的情况)
所以我们d[i]的计算条件一定要有两个,A[i]>A[j]&&dp[j]>=dp[i]
最后:如果你能看到最后并且看懂也是牛批,如果没看明白建议去看看我给出链接的博主博客
有不对的地方欢迎指出