一.概念介紹
動態規劃(dynamic programming),簡稱dp.是把多階段過程轉化為一系列單階段問題,利用各階段之間的關係,逐個求解,創立了解決這類過程優化問題的新方法.
二.特點
動態規劃演算法通常基於乙個遞推公式及乙個或多個初始狀態。當前子問題的解將由上一次子問題的解推出。使用動態規劃來解題只需要多項式時間複雜度,因此它比回溯法、暴力法等要快許多。
在解決問題時,推導出狀態轉移方程是關鍵所在.
三.舉例
1.最少硬幣問題
待續...
2.lcs問題
最長公共子串行的長度問題的推導公式為:
從公式可知,這個問題可以用遞迴的方式來實現,**:
1view code//遞迴實現方法 lcs(i,j)即公式中的c[i,j]
2int lcs(int i, intj)3
18 }
遞迴實現雖然好理解,但是存在缺陷,不能記錄所有的資料改變的記錄,而資料改變的記錄可以在長度外,幫助找到子串行.
用陣列pd代替公式中的二維陣列c[i][j],完成上述公式的**如下:
1 #include2 #include3 #includeview code4using
namespace
std;
5char a[10], b[10];6
intlena, lenb;78
void
lcs();
9int
main()
1022
void
lcs()
2340
else
4145}46
}4748 cout <
49 cout <
50 }
用陣列實現的時候,有乙個好處,我們發現了乙個規律,相同字元所對應的c[i][j]的賦值一定是它左上側c[i-1][j-1]的值加一得來的,如下圖所示,所以我們通過倒序遍歷陣列c的賦值過程,可以得到最長自序列.
倒序遍歷時,我們需要記載當前c[i][j]被賦值時的方向,引入了乙個陣列來記載c[i][j]的賦值方向.然後倒序遍歷則可以得到結果,**如下:
1 #include2 #include3 #includeview code4using
namespace
std;
5char a[10], b[10];6
intlena, lenb;78
int lcs(int, int); ///
兩個引數分別表示陣列a的下標和陣列b的下標
9void
lcs();
10int
main()
1123
24void
lcs()
25 };
30//
用來記錄賦值的方向
31char dpd[11][11
];32
3334
//公式第一段
35 dp[0][0] = 0;36
for (int i = 0; i < m; i++)
3747
else
4858
else
5964
65 dp[i + 1][j + 1] =t;66}
67}68}
6970 cout <
71 cout <
7273
while (m>=0&&n >= 0)74
8283
switch
(dpd[m][n])
8496}97
98 }
結果:
3.遞增子串行問題
遞推公示:length[i]=a[i]>a[0...i-1]?length[i-1]+1:max
動態規劃 最長遞增子串
給定乙個陣列nums,求其最長的遞增子串長度。如陣列 10,9,2,5,3,7,101,18 其最長遞增子串為 2,3,7,101 長度為4.方法一 直接遍歷,複雜度為o n 2 方法二 把長度為i 1的遞增子串的最後元素的最小值記錄在陣列tails中,如對於陣列 4,5,6,3 tails中的記錄...
動態規劃 最長遞增子串行
給出序列 1 2 3 4 2 5 3 4 a 1 1,a 2 2,a 7 3,a 8 4 求其最長的遞增子串行,以上最長遞增子串行為 1 2 3 4 5 問題細分 初始化條件f 1 1,序列只有1個長度即為1 f 2 a 2 與下標小於2的比較,即a 1 比較,a 2 a 1 因此更新f 2 f 1...
動態規劃 最長遞增子串行
給定乙個無序的整數陣列,找到其中最長上公升子串行的長度 例項 輸入 10,9,2,5,3,7,101,18 輸出 4 解釋 最長的上公升子串行為 2,3,7,101 長度為4說明 可能會有多種最長上公升子串行的和,只需要輸出對應長度即可 演算法的時間複雜度應為o n2 首先,dp陣列的定義如下 dp...