題目
東東有兩個序列a和b。
他想要知道序列a的lis和序列ab的lcs的長度。
注意,lis為嚴格遞增的,即a1input
第一行兩個數n,m(1<=n<=5,000,1<=m<=5,000)
第二行n個數,表示序列a
第三行m個數,表示序列b
output
輸出一行資料ans1和ans2,分別代表序列a的lis和序列ab的lcs的長度
****** input
5 51 3 2 5 4
2 4 3 1 5
****** output
3 2解題思路
lis: 最長上公升子串行
例:c= 1 2 3 4 5 0 9
最長上公升序列為 1 2 3 4 5 9
lcs: 最長公共子串行
例: a = 1 5 2 6 8 7
b = 2 3 5 6 9 8 4
lcs 為5 6 8或 2 6 8
求lis的長度:
兩重迴圈,外層迴圈遍歷c,從0到n
內層迴圈從0到 i
cnt陣列記錄[ 0, i ] 的最長上公升子串行
也就是說,c[0,4] 記錄了 到4 的 lis的長度
cnt[i] = max ( cnt[j] + 1, cnt[i] )
遍歷到c[j] ,如果從 c[j] 直接跳到了c[i] ,那麼長度為多少 , 然後和 cnt[i]比較,取最大值
lcs的長度:
一維陣列無法記錄全部資訊,所以有二維陣列記錄 f
同樣2重迴圈,更新f[i][j] ,表示 a [ 1 , i ] , b [ 1 , j ] 的最長公共子串行的長度
**實現
#include
using
namespace std;
#include
#define ll long long
ll a[
5005];
ll b[
5005];
int cnt[
5005];
int f[
5005][
5005];
int n,m;
intlis()
;int
lcs();
intmain()
for(
int i=
0;i) cin>>b[i]
;int res1,res2;
res1=
lis();
res2=
lcs();
cout<" "
}int
lis()}
}int res=-1
;for
(int i=
0;i)return res;
}int
lcs(
)//從1到n,m的
}return f[n]
[m];
}
小結
動態規劃的**不長,但是確實非常考驗思維,只要找到狀態轉移方程,就不難了。
動態規劃 什麼是動態規劃?
先來看看 資訊學奧賽一本通第5版 是怎麼說的 動態規劃程式設計是對解最優化問題的一種途徑 一種方法,而不是一種特殊演算法。不像前面所述的那些搜尋或數值計算那樣,具有乙個標準的數學表示式和明確清晰的解題方法。動態規劃程式設計往往是針對一種最優化問題,由於各種問題的性質不同,確定最優解的條件也互不相同,...
mysql動態規劃 動態規劃
動態規劃 能夠動態規劃的問題具有以下特點 可分解成規模更小的子問題 子問題的結果可復用 關鍵是要理解狀態轉移方程的含義就好啦!數字三角形 問題描述 在數字三角形尋找從頂到底的路徑,使得路徑經過的數字之和最大。規定每一步只能往左下或右下走,求出最大路徑和。遞迴解法 include include us...
《動態規劃》 ACM 動態規劃例題詳解
描述 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 圖1 圖1給出了乙個數字三角形。從三角形的頂部到底部有很多條不同的路徑。對於每條路徑,把路徑上面的數加起來可以得到乙個和,你的任務就是找到最大的和。注意 路徑上的每一步只能從乙個數走到下一層上和它最近的左邊的那個數或者右邊的那個數。輸...