DP思路:
需要求 S(x)的LIS 可以先求 S(x-1)的LIS,
求S(x-1)的LIS 可以先求S(x-2)的LIS,
......
由此看出,后一个状态可以由前一个状态得出,所以可以用递推
假设:
集合 S(x) 为 长度为 x 的数字串 (x=1,2,3,4.......)
集合 LIS(y) 为 长度为 y 的最长递增子序列(y=1,2,3,4......);
L[i] : S(i)的 LIS长度 ,用于记录S(x)不同长度时候的LIS长度。 (i=1,2,3,4.....)
那么:
当 S[i] > LIS[y] 时候(即找到符合递增的数值),LIS[++y] = S[i] (0<i<x)
当 S[i] < LIS[y] 时候,则从 LIS[y] 向前寻找 比S[i]小 的数值 LIS[k] ,然后用S[i]替换LIS[k+1] ,即 LIS[k+1]=S[i]
例如
S(x) = (1,2,3,9,10,8)
LIS(y) =(1,2,3,9,10)
则,当 i=4 的时候
LIS(y) 就会变成 (1,2,3,8,10)
最后推出的 y 便是LIS的长度。
转移方程 :
{
L[k]= L[k-1] +1 (数值符合递增时)
L[k]= L[k-1] (数值不符合递增时)
#include<iostream>
using namespace std;
int main() {
int S[100], LIS[100] = { 0 };
int L[100] = { 0 };
LIS[0] = -1;
int n, i, k, y = 0;
cin >> n;
for (i = 0; i < n; i++)cin >> S[i];
for (i = 0; i < n; i++) {
if (S[i] == LIS[y])continue;
if (S[i] < LIS[y]) {
L[i+1] = L[i];
int k = y;
while(k--)
if (S[i] > LIS[k]) {
LIS[k + 1] = S[i];
break;
}
}
else {
LIS[++y] = S[i];
L[i + 1] = L[i] + 1;
}
}
for (i = 1; i <= n; i++)cout << L[i];
return 0;
}