c 動態規劃基礎 最長上公升子串行

2021-08-08 21:15:37 字數 1697 閱讀 1004

這次博主帶來的是動態規劃的一道基礎題——最長上公升子串行

希望可以對比較迷茫的小夥伴帶來幫助!

以下為題目

最長上公升子串行:

描述

乙個數的序列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 9 3 4 。貪心只可以看到1 9,結果不能找到1 3 4。對於這道題,我們可以用動態規劃(dp)。

思路 動態規劃的關鍵在於定義陣列的含義和「狀態轉移方程式」。這裡我們可以定義乙個陣列 a[i] 來存數列,再定義 f[i] 用來表示末尾為 a[i] 的最長上公升子串行。這句話非常重要!

狀態轉移方程式

當 a[i]>a[j] 時,f[i]=max(f[j]+1,f[i]); 這裡的max為取較大值,也就是f[i]為它本身和 f[j]+1 中較大的乙個。有乙個問題:f[i] 為什麼要和自己比較呢,因為在迴圈中,f[i] 可能賦過很多次值。

當 a[i]<=a[j]時, f[i]就不能變,因為 a[i] 不能接在 a[j] 後面。

最後再在末尾為 1,2,3,…,n 的最長上公升子串行中找到最長的那乙個既是正確答案!

實現 這裡就直接給**了:

#include

#include//這個標頭檔案可以使用max(,),*max_element(,)

using

namespace

std; //它們的含義分別是:求兩者最大;求陣列最大

int n,a[1002],f[1002];

int main()

for(int i=1;i<=n;i++) //列舉i的位置

for(int j=1;j//在i的前面找j的位置

if(a[i]>a[j]) //如果滿足條件,則第i個數可以放在j後邊

f[i]=max(f[j]+1,f[i]);//取較大的一種再放

printf("%d",*max_element(f+1,f+n+1));//從 f[1]到f[n] 找最大值

return

0;}

那麼這一道題就做完了!

但是這道題也有許多「變式」,例如:最長下降子串行,最長公共上公升子串行……

這道題作為一道基礎也隱藏在許多題目中,如:攔截飛彈,渡輪問題等。

所以一定要把這道題了解清楚,才可以在更多的領域取得更好的成績啊!

動態規劃 最長上公升子串行

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

動態規劃 最長上公升子串行

動態規劃 儲存遞迴中間結果,減少遞迴次數 總時間限制 2000ms 記憶體限制 65536kb 描述 乙個數的序列 bi,當 b1 b2 bs的時候,我們稱這個序列是上公升的。對於給定的乙個序列 a1,a2 an 我們可以得到一些上公升的子串行 ai1,ai2 aik 這裡1 i1 i2 ik n。...

動態規劃 最長上公升子串行

總時間限制 2000ms 記憶體限制 65536kb 描述乙個數的序列bi,當b1 b2 bs的時候,我們稱這個序列是上公升的。對於給定的乙個序列 a1,a2,an 我們可以得到一些上公升的子串行 ai1,ai2,aik 這裡1 i1 i2 ik n。比如,對於序列 1,7,3,5,9,4,8 有它...