递推求LIS

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;
}








猜你喜欢

转载自blog.csdn.net/qq742762377/article/details/80861519
lis
今日推荐