openjudge 2757:最長上升子序列

總時間限制: 2000ms 內存限制: 65536kB


描述
一個數的序列bi,當b1 < b2 < ... < bS的時候,我們稱這個序列是上升的。對於給定的一個序列(a1, a2, ..., aN),我們可以得到一些上升的子序列(ai1, ai2, ..., aiK),這裏1 <= i1 < i2 < ... < iK <= N。比如,對於序列(1, 7, 3, 5, 9, 4, 8),有它的一些上升子序列,如(1, 7), (3, 4, 8)等等。這些子序列中最長的長度是4,比如子序列(1, 3, 5, 8).

你的任務,就是對於給定的序列,求出最長上升子序列的長度。
輸入
輸入的第一行是序列的長度N (1 <= N <= 1000)。第二行給出序列中的N個整數,這些整數的取值範圍都在0到10000。
輸出

最長上升子序列的長度。


樣例輸入
7

1 7 3 5 9 4 8


樣例輸出

4


解題思路:

1.找子問題

“求序列的前n個元素的最長上升子序列的長度”是個子問題,但是這樣分解子問題
不具有“無後效性”

假設F(n) = x,但可能有多個序列滿足F(n) = x,有的序列的最後一個元素比an+1小
,則加上an+1就能想成更長上升子序列;有的序列最後一個元素不必an+1小...故以後
的情形將受到狀態n的影響,不符合“無後效性”

2.確定狀態

子問題之和一個變量--數字的位置有關。因此序列中數字的位置k就是狀態,而狀態
k對應的值就是以ak作爲終點的最長上升子序列的長度。
狀態一共有N個。

3.確定一些初始狀態
在本狀態的初始狀態中是將狀態數組len[i]初始化爲1.

4.找出狀態轉移方程

maxLen (k)表示以ak做爲“終點”的
最長上升子序列的長度那麼:
初始狀態:maxLen (1) = 1
maxLen (k) = max { maxLen (i):1<=i < k 且 ai < ak且 k≠1 } + 1
若找不到這樣的i,則maxLen(k) = 1
maxLen(k)的值,就是在ak左邊,“終點”數值小於ak ,且長度最大的那個上升子序
列的長度再加1。因爲ak左邊任何“終點”小於ak的子序列,加上ak後就能形成一個更長
的上升子序列。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;


const int maxn = 1010;

int a[maxn],len[maxn];
int n;

int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d",&a[i]);
        len[i] = 1;
    }
    //“人人爲我”遞推版動歸程序
    /*for(int i=0;i<n;i++){
        for(int j=0;j<i;j++){
            if(a[j]<a[i])
                len[i] = max(len[i],len[j]+1);
        }
    }*/
    //"我爲人人"版
    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            if(a[j]>a[i])
                len[j] = max(len[j],len[i]+1);
        }
    }
    int Max = -1;
    for(int i=0;i<n;i++)
        Max = max(Max,len[i]);
    printf("%d\n",Max);
    printf("%d\n",*max_element(len,len+n));
    return 0;
}


發佈了70 篇原創文章 · 獲贊 47 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章