動態規劃 最長非降子串行

2021-07-11 07:55:36 字數 1598 閱讀 5119

先分享一篇文章《動態規劃:從新手到專家》,作者正是通過這篇文章來學習的。文中對動態規劃的設計思想做了非常詳細的介紹,並通過簡單問題和複雜問題對動態規劃的設計流程進行剖析,以下是作者和出處:

先介紹下問題,給定長度為n的整數序列:a[1], a[2], ......, a[n],求得其中最長非降子串行的長度,即lis(longest increasing subsequence)。比如如下的整數序列:

5, 3, 4, 8, 6, 7

其最大非降子串行即為3, 4, 6, 7,長度為4。

那麼如何用動態規劃來求解這個問題呢?動態規劃中最重要的一部分就是定義狀態轉移方程,在這個問題中,如果我們定義d[i]為序列a[1], a[2], ..., a[i]的最長非降子串行,但很可惜,在後面思考中,我發現,d[i]和d[i-1]之間很難建立起狀態轉移關係,a[1]~a[i-1]和a[1]~a[i]二者的最長非降子串行間不一定有公共的部分,如1, 4, 2, 5, 3中前四個整數和前五個整數的最大非降子串行不一定有共同的部分,無法建立起狀態轉移關係。但如果用d[i]表示以元素a[i]結束的最長非降子串行的長度,那狀態方程就有規律可循了,我們以上面的序列為例:

d(1) = max; //只有5

d(2) = max; //3之前沒有比3小的

d(3) = max = 2; //4之前有3

d(4) = max = 3; //8之前有3, 4

d(5) = max = 3; //6之前有3, 4

d(6) = max = 4; //7之前有3, 4, 6

lis = max(d[i]) = 4, 1 <= i < = 6

從上面的流程來看,先求出這個序列中以每個元素作為結尾的最大非降子串行的長度,那問題的解總是以序列中某個元素作為結尾的,所以取最大值即可。而且從上面的公式我們很容易看出求d[i]的過程,簡單來說,就是從i往前找,如果某個元素a[j] < = a[i],那麼以元素a[j]結尾的最長非降子串行再加上a[i]一定也是乙個非降子串行,d[j] + 1肯定是乙個非降子串行長度,找到所有符合條件的j,所有符合條件的d[j] + 1的最大值就一定是d[i]的值。從另乙個角度去看,因為以a[i]為結尾的最長子序列的倒數第二個元素(假設長度不小於2)肯定是a[i]之前的某乙個元素,所有a[j]作為倒數第二個元素的序列就是以a[i]為結尾的子串行。當然,還要考慮特殊的情況,假設a[i]之前沒有比其更小的元素,則子串行就是其本身,長度為1。綜上所述,狀態轉移方程如下:

d[i] = max(1, max(d[j] + 1)), 1 <= j < i, a[j] <= a[i];

最後問題的解即為:

lis = max(d[i]); 1 <= i <= n, n為序列的長度

#include using namespace std;

int lis(int data, int n)}}

if(d[i]>len) len = d[i];

}return len;

}int main()

; cout << lis(data, 6) << endl;

return 0;

}

動態規劃 最長非降子串行

乙個序列有n個數 a 1 a 2 a n 求出最長非降子串行的長度。講dp基本都會講到的乙個問題lis longest increasing subsequence 正如上面我們講的,面對這樣乙個問題,我們首先要定義乙個 狀態 來代表它的子問題,並且找到它的解。注意,大部分情況下,某個狀態只與它前面...

動態規劃之最長非降 公升 子串行

問題描述 在乙個無序的序列a1,a2,am裡,找到乙個最長的序列,滿足ai aj.ak 且i問題分析 如果前i 1個數中的最長非降子串行的最後乙個數是ak 那麼下一步就是在求前k 1個數中的的最長非降子串行 因此我們可以設計乙個狀態opt j 表示前i個數中用到a i 所構成的最優解 核心 那麼決策...

動態規劃之最長非遞減子串行

在乙個數字序列中,找到乙個最長的非連續子串行,使得這個子串行是不下降 非遞減 現有序列a 則a的最長不下降子串行是。如果有多個最長序列,只需選數字順位靠後的序列從大到小輸出。輸入2行 第一行乙個整數n,表示有n個整數的序列要輸入,n 1000 第二行共有n個整數。輸出最長的不下降子串行,只需選數字順...