第九章 動態規劃 1306 最長公共子上公升序列

2021-10-05 15:33:47 字數 1835 閱讀 4297

1306:最長公共子上公升序列

時間限制: 1000 ms 記憶體限制: 65536 kb

提交數: 1808 通過數: 1006

【題目描述】

給定兩個整數序列,寫乙個程式求它們的最長上公升公共子串行。

當以下條件滿足的時候,我們將長度n的序列s1,s2,…,sn 稱為長度為m的序列a1,a2,…,am的上公升子串行:

存在1≤i1【輸入】

每個序列用兩行表示,第一行是長度m(1≤m≤500),第二行是該序列的m個整數ai(−231≤ai<231)

【輸出】

在第一行,輸出兩個序列的最長上公升公共子串行的長度l。在第二行,輸出該子串行。如果有不止乙個符合條件的子串行,則輸出任何乙個即可。

【輸入樣例】

51 4 2 5 -12

4-12 1 2 4

【輸出樣例】

21 4

思路:a[i] != b[j]時, d[i][j] = d[i-1][j]; 因為 d[i][j] 是以 b[j] 為結尾的lcis,如果 d[i][j] > 0 那麼就說明 a[1] … a[i] 中必然有乙個元素 a[k] 等於 b[j]。因為 a[k] != a[i],那麼 a[i] 對 d[i][j] 沒有貢獻,於是我們不考慮它照樣能得出 d[i][j] 的最優值。所以在 a[i] != b[j] 的情況下必然有 d[i][j] = d[i-1][j]。

狀態轉移方程:

a[i] != b[j]: d[i][j]=d[i-1][j] ;

a[i] == b[j]: d[i][j]=max(d[i-1][k]) + 1 ; (1<= k <= j-1)

這是乙個時間複雜度為o(n^3)的dp.

如何變成o(n^2),保證到i、j為止的最大長度不可能小於i-1,j的,/只要以乙個序列為準記住p就可以,i不變,遍歷j,此時要保證j序列值要小才可以是上公升序列,if (a[i] > b[j] && mx < dp[i-1][j]),記錄dp[i-1][0~j]的最大值,記錄此時的j值,if (a[i] == b[j]) ,dp[i][j] = mx+1;p[i][j] = y;ans = max(ans,dp[i][j]);就是最後所求。

#include

#include

#include

#include

#define n 505

using

namespace std;

long

long a[n]

,b[n]

,k[n]

;int dp[n]

[n]=

,p[n]

[n1]

;int

main()

else

if(a[i]

== b[j]

) ans =

max(ans,dp[i]

[j]);}

} cout << ans << endl;

int t =1;

for(j =

2;j <= m;j++

)//看作一位陣列,找最大的序列的末尾為止,也可以在上面的ans更新

if(dp[n]

[j]> dp[n]

[t])

t = j;

int top =0;

i = n;j = t;

while

(dp[i]

[j])

for(i = top-

1;i >=

0;i--

) cout << k[i]

<<

" ";

cout << endl;

return0;

}

第九章 動態規劃 1305 Maximum sum

輸入樣例 110 1 1 2 2 3 3 4 4 5 5 輸出樣例 13 提示 就是求最大子段和問題,樣列取2,2,3,3,4和5,baidu搜poj 2479 maximum sum,可獲得大量經典最大子段和問題的題目解析,本題o n2 演算法超時,必須用o n 演算法。思路 從左到右分別求出它們...

第九章 動態規劃 1300 雞蛋的硬度

1300 雞蛋的硬度 時間限制 1000 ms 記憶體限制 65536 kb 題目描述 最近xx公司舉辦了乙個奇怪的比賽 雞蛋硬度之王爭霸賽。參賽者是來自世界各地的母雞,比賽的內容是看誰下的蛋最硬,更奇怪的是xx公司並不使用什麼精密儀器來測量蛋的硬度,他們採用了一種最老土的辦法 從高度扔雞蛋 來測試...

第九章 動態規劃 1301 大盜阿福

1301 大盜阿福 時間限制 1000 ms 記憶體限制 65536 kb 提交數 3388 通過數 1400 題目描述 阿福是一名經驗豐富的大盜。趁著月黑風高,阿福打算今晚洗劫一條街上的店鋪。這條街上一共有 n 家店鋪,每家店中都有一些現金。阿福事先調查得知,只有當他同時洗劫了兩家相鄰的店鋪時,街...