1錯筆記 最長遞增子串行 一維動態規劃

2021-10-10 07:19:00 字數 1539 閱讀 6921

給定乙個長度為n(1 <= n <= 1000)的整數序列a[i],求它的乙個子串行(子串行即在原序列任意位置刪除0或多個元素後的序列),滿足如下條件:

1、該序列單調遞增;

2、在所有滿足條件1的序列中長度是最長的;

最近剛好在學習動態規劃,不得不說dp實在太博大精深了,恰好看到這篇那麼好的文章,就記錄下其中一些例題的解題過程,也方便自己feedback

之前刷的dp都是二維的,今天這道題是一維的(其實這道題也可以轉化為用最長公共子串二維來解,但要)

之前有詳細講解過最長公共子串行和最長回文子串行的解法,這裡就不贅述了。

在理解完題意後,列舉固然是一種方法,只要把全部的可能性列出來然後逐一檢查就能找到答案,但卻不是可行的方法,因為2^(1000)是指數**級別的。

嗯,既然列舉這種方法是肯定不行的,那麼這種演算法其中有沒有我們值得學習和借鑑的呢?

有,通過這篇部落格,我們可以大概把dp理解為記憶化的dfs,那麼在列舉的過程中我們可不可以通過記憶減少複雜度呢?

因為在傳統的列舉過程中,每次列舉的情況,我們都要從頭開始算它到底有多少符合條件的子串行,這也是為什麼列舉的複雜度是2^(1000)。那我們每一次列舉可不可以站在巨人的肩膀上,從上一次列舉的已經記錄下來的結果推導出來呢?

那,這不就是dp的狀態轉移方程嗎?

如何設計呢?建議看到這裡的你先暫停一下,自己思考設計下狀態轉移方程。下面進行解密。

為了更形象一點,我先舉個例子

假設有數列

1,4,6,3,8,2,9,11,2,60
肉眼就能判斷出最長遞增子串行是

1,4,6,8,9,11,60
我們一開始從第乙個數開始檢索,無論第乙個數多大,最長遞增子串行到目前為止就是1(因為就它乙個呀,沒有大小之分),到第二個,就要判斷它是否比1大了,如果大,恭喜!加入子串行,反之則不加入。

假定我們用dp[i]來記憶截至到數列a[i]時的最長遞增子串行

那麼,就很容易推算出,當檢索到a[j]的時候dp[j]的值肯定是dp[0]-dp[j-1]的值中最大的那個+1(當然要符合遞增條件的前提下)

因為截至到每乙個數時都有很多可能,比如當i為4時,他的子串行有

1,4,6,3

1,4,6

1,4,3

1,6,3

......

但其中最長的且符合條件的只有1,4,6

那麼在i為5的時候,就可以看前面最大的dp是多少,然後如果i符合條件(遞增條件)就+1,如果不符合條件,那它就沒有任何價值了。

#include using namespace std;

int main()

; int dp[10];

int i,j;

int len = sizeof (a) / sizeof (a[0]);

//預設全部為1,就是以自己為起點

for ( i=0; ia[i] && dp[j]max ) max = dp[i];

cout<}

動態規劃 最長遞增子串行

給出序列 1 2 3 4 2 5 3 4 a 1 1,a 2 2,a 7 3,a 8 4 求其最長的遞增子串行,以上最長遞增子串行為 1 2 3 4 5 問題細分 初始化條件f 1 1,序列只有1個長度即為1 f 2 a 2 與下標小於2的比較,即a 1 比較,a 2 a 1 因此更新f 2 f 1...

動態規劃 最長遞增子串行

給定乙個無序的整數陣列,找到其中最長上公升子串行的長度 例項 輸入 10,9,2,5,3,7,101,18 輸出 4 解釋 最長的上公升子串行為 2,3,7,101 長度為4說明 可能會有多種最長上公升子串行的和,只需要輸出對應長度即可 演算法的時間複雜度應為o n2 首先,dp陣列的定義如下 dp...

動態規劃 最長遞增子串行

最長遞增子串行是動態規劃中最經典的問題之一,該問題描述的是在乙個已知序列中,取出若干元素 不必連續 組成乙個新的序列,子串行的各個數先後順序保持不變,且對子序列中的任意下標x令dp i 表示以a i 作為末尾的最長遞增子串行的長度。於是,通過設定這麼乙個陣列,最長遞增子串行的長度便是陣列dp中的最大...