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

2021-08-21 22:30:06 字數 1217 閱讀 7034

原文 

主題 動態規劃

最長上公升子串行問題,也就是longest increasing subsequence,縮寫為lis。是指在乙個序列中求長度最長的乙個上公升子串行的問題,是動態規劃中乙個相當經典問題。在這裡我們可以看到,這個上公升實質上就是乙個對<進行定義的過程,所以我們求解的其實是一類問題,也就是在給定序列中求解長度最長的符合某一性質的子串行的問題。在下面總結的過程中,我還是以遞增為例進行闡述。

dp[i]表示以i結尾的子串行中lis的長度。然後我用dp[j](0<=ja[j]的時候,我們需要進行判斷,是否將a[i]加入到dp[j]當中。為了保證我們每次加入都是得到乙個最優的lis,有兩點需要注意:第一,每一次,a[i]都應當加入最大的那個dp[j],保證區域性性質最優,也就是我們需要找到max(dp[j](0<=j

如果寫成遞推公式,我們可以得到dp[i]=max(dp[j](0<=ja[j]?1:0)

於是我們就能夠得到o(n^2)的動態規劃方法的實現:

const int maxn = 1010;

int n;

int a[maxn];

int dp[maxn]; int lis() } dp[i] = max + 1; } max = 0; for (int i = 0; i < n; ++i) return max; }

在前一種方法中,我們花費了很多時間在尋找最大的dp[j]上。如果有辦法讓這個dp[j]變成乙個遞增的序列,我們就能使用二分來進行優化,從而使得複雜度下降為o(nlogn)了。幸運的是,這種方法確實是存在的。我們可以使用dp[i]來儲存在前i個數中最大的那個數,很容易可以理解,這個dp[i]已經是單調不減的。接下來的處理其實有些貪心的思想,對於每乙個a[i],我們都在dp陣列中尋找比它大的第乙個數的下標,不妨設為pos,然後用a[i]來更新dp[pos]。於是我們可以明白,len就應當是max(len, pos+1)。

在這裡我們使用 lower_bound函式 ,這個函式將會返回小於等於val的第乙個值的指標,如果不存在就返回end指標。

const int maxn = 1010;

int n;

int a[maxn];

int dp[maxn]; int lis() return len; }

最長上公升子串行問題(動態規劃)

乙個數的序列bi,當b1 n。比如,對於序列 1,7,3,5,9,4,8 有它的一些上公升子串行,如 1,7 3,4,8 等等。這些子串行中最長的長度是4,比如子串行 1,3,5,8 你的任務,就是對於給定的序列,求出最長上公升子串行的長度。輸入輸入的第一行是序列的長度n 1 n 1000 第二行給...

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

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