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 家店鋪,每家店中都有一些現金。阿福事先調查得知,只有當他同時洗劫了兩家相鄰的店鋪時,街...