最長上公升子數列

2021-08-05 23:04:45 字數 1418 閱讀 4358

最長上公升子數列

輸入

第1行:1個數n,n為序列的長度(2 <= n <= 50000)

第2 - n + 1行:每行1個數,對應序列的元素(-10^9 <= s[i] <= 10^9)

輸出

輸出最長遞增子串行的長度。

輸入示例

851

6824

510

輸出示例

5

(lis longest increasing subsequence)給定乙個數列,從中刪掉任意若干項剩餘的序列叫做它的乙個子串行,求它的最長的子串行,滿足子串行中的元素是單調遞增的。

例如給定序列,答案是3,因為和就是長度最長的兩個單增子序列。

處看此題,怎麼做? 萬能的列舉?列舉全部2^n個子序列,找出最長的,固然可以,就是複雜度太高。我們為什麼要列舉呢?因為要知道取了哪些數,其實我們只需要考慮上乙個數和取了幾個數就可以了吧?因為單增的意思是比前乙個數大,我們要加入這個數的時候,只考慮它比之前加入的最後乙個數大就可以了。而最長的意思是數的個數最多,我們只要知道數的總個數就可以了,沒必要知道具體有哪些數。

讓我們嘗試一下用動態規劃的思考辦法。首先設定數列是a1, a2, a3…an,為了方便我們加入一項a0=-∞,後面我們將發現這會給我們帶來極大的方便。int f[i]表示以第i個數結尾的最長單調子串行的長度, 那麼我們看一下加入ai之前的最後乙個數是aj,顯然j < i並且aj < ai,我們有f(i) = f(j) + 1,因為往後面延長了一項嘛。那根據這個式子,我們顯然應該選擇最大的f(j),才能讓f(i)最大。

於是我們有了遞推關係f(i) = max + 1,光有了遞推關係還不夠,初值呢? f(0) = 0,並且我們加入了a0=-∞,這樣對每個i > 0,j總是存在的,大不了就達到下標0了嘛。

**:

//o(n^2)時間複雜度

#include #include #include using namespace std;

const int maxn = 50010;

int dp[maxn], a[maxn];

int main()

{ int n;

while(scanf("%d",&n)!=eof)

{ for(int i=0;i#include #define inf 0x3f3f3f

using namespace std;

int dp[50010],a[50010];

int main()

{ int n,i,j;

while(scanf("%d",&n)!=eof)

{ for(i=0;i

Dp 最長上公升子串 最長上公升子串行

乙個數的子串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,5,9 等等。這些子串中最長...

最長上公升子串行

問題描述 乙個數的序列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 等等...

最長上公升子串行

最長上公升子串行問題是各類資訊學競賽中的常見題型,也常常用來做介紹動態規劃演算法的引例,筆者接下來將會對poj上出現過的這類題目做乙個總結,並介紹解決lis問題的兩個常用 演算法 n 2 和 nlogn 問題描述 給出乙個序列a1,a2,a3,a4,a5,a6,a7.an,求它的乙個子串行 設為s1...