LIS模型——最长上升子序列(Longest Increasing Subsequence)
【例1】最长上升子序列
Description
一个数的序列bi,当b1< b2 < ... < bS的时候,我们称这个序列是上升的。对于给定的一个序列(a1,a2,...,aN),我们可以得到一些上升的子序列(ai1, ai2, ..., aiK),这里1<=i1
你的任务,就是对于给定的序列,求出最长上升子序列的长度。
Input
输入的第一行是序列的长度N(1<=N<=1000)。第二行给出序列中的N个整数,这些整数的取值范围都在0到10000。
Output
最长上升子序列的长度。
Sample Input
6
1 6 2 5 4 7
Sample Output
4
【问题分析】
1、阶段和状态:
f[i]:表示以a[i]为结尾的最长上升子序列的最大长度;
阶段i表示前i个数,由于每个阶段只有一个状态,所以用一维数组表示;
2、状态转移方程:
初始化:f[i]=1;
每个元素至少都满足以自身作为长度为1的最长上升子序列。
状态转移:f[i]=max{f[j]+1,j<i且a[j]<a[i]}
利用1~(i-1)的f[j]更新当前位置f[i]的最大长度,如果a[i]>a[j],表明以a[i]可以接在a[j]后得到更长的LIS。
遍历答案:answer=max{f[i]};(1<=i<=n)
遍历每个元素a[i]结尾得到的最大上升子序列的长度,得到最大长度。
【图表演示】
【核心代码】
cin>>n;
for(i=1; i<=n; i++)
{
cin>>a[i]; //初始化
f[i]=1;
}
for(i=2; i<=n; i++)
for(j=1; j<i; j++)
if(a[j]<a[i]&&f[j]+1>f[i]) f[i]=f[j]+1;
max=1;
for(i=1; i<=n; i++)
if(f[i]>f[max])max=i;
cout<<f[max]<<endl;
【扩展1】最长不下降子序列
Description
设有整数序列b1,b2,b3,……,bm, 若存在i1< i2 <i3 <…… <in,且bi1<bi2<bi3……<bin,
则称b1,b2,b3,……,bn,中有长度为N的不下降序列bi1,bi2,bi3,……,bin。求序列b1,b2,b3,……,bm中最大不下降序列的长度。
Input
第一行为n,第二行为用空格隔开的n个整数。
Output
第一行为输出最大个数max。
Sample Input
14
13 7 9 16 38 24 37 18 44 19 21 22 63 15
Sample Output
8【题目提示】
最长不上子序列,a[i]与a[j]之间不相等
最长不下降子序列,a[i]与a[j]可以相等
【扩展2】最长不下降子序列
Description
设有整数序列b1,b2,b