動態規劃演算法經典案例

2021-07-10 04:51:10 字數 4269 閱讀 7728

動態規劃演算法是從暴力搜尋演算法優化過來的,如果我們不清楚暴力搜尋的過程,就難以理解動態規劃的實現,當我們了解了動態規劃演算法的基本原理的文字概述,實現條件之後,這時可能並不是太理解這種思想,去面對實際問題的時候也是無從下手,這個時候我們不能停留在文字層面上,而應該去學習經典動態規劃演算法的實現,然後倒回來看這些概念,便會恍然大悟。

動態規劃演算法的難點在於 從實際問題中抽象出動態規劃表dp,dp一般是乙個陣列,可能是一維的也可能是二維的,也可能是其他的資料結構。

動態規劃的關鍵點:

1、最優化原理,也就是最有子結構性質。這指的是乙個最優化策略具有這樣的性質,無論過去狀態和決策如何,對前面的決策所形成的狀態而言,餘下的決策必須構成最優策略,簡單來說就是乙個最優化策略的子策略總是最優的,如果乙個問題滿足最優化原理,就稱其有最優子結構性質。

2、無後效性,指的是某個狀態下的決策的收益,只與狀態和決策相關,與達到該狀態的方式無關。

3、子問題的重疊性,動態規劃將原來指數級的暴力搜尋演算法改進到了具有多項式時間複雜度的演算法,其中的關鍵在於解決了榮譽,重複計算的問題,這是動態規劃演算法的根本目的。

4、總體來說,動態規劃演算法就是一系列以空間換取時間的演算法。

案例一:

有n級台階,乙個人每次上一級或者兩級,問有多少種走完n級台階的方法。

分析:動態規劃的實現的關鍵在於能不能準確合理的用動態規劃表來抽象出 實際問題。在這個問題上,我們讓f(n)表示走上n級台階的方法數。

那麼當n為1時,f(n) = 1,n為2時,f(n) =2,就是說當台階只有一級的時候,方法數是一種,台階有兩級的時候,方法數為2。那麼當我們要走上n級台階,必然是從n-1級台階邁一步或者是從n-2級台階邁兩步,所以到達n級台階的方法數必然是到達n-1級台階的方法數加上到達n-2級台階的方法數之和。即f(n) = f(n-1)+f(n-2),我們用dp[n]來表示動態規劃表,dp[i],i>0,i<=n,表示到達i級台階的方法數。

/*dp是全域性陣列,大小為n,全部初始化為0,是題目中的動態規劃表*/

int fun(int n)

案例2:

給定乙個矩陣m,從左上角開始每次只能向右走或者向下走,最後達到右下角的位置,路徑中所有數字累加起來就是路徑和,返回所有路徑的最小路徑和,如果給定的m如下,那麼路徑1,3,1,0,6,1,0就是最小路徑和,返回12.

1 3 5 9

8 1 3 4

5 0 6 1

8 8 4 0

分析:對於這個題目,假設m是m行n列的矩陣,那麼我們用dp[m][n]來抽象這個問題,dp[i][j]表示的是從原點到i,j位置的最短路徑和。我們首先計算第一行和第一列,直接累加即可,那麼對於其他位置,要麼是從它左邊的位置達到,要麼是從上邊的位置達到,我們取左邊和上邊的較小值,然後加上當前的路徑值,就是達到當前點的最短路徑。然後從左到右,從上到下依次計算即可。

#include #include using namespace std;

int dp[4][4] = {};

int main();

//cout << fun(arr,4,4) << endl;

const int oo = ~0u>>2;

for (int i = 0;i<4;i++)

for (int j = 0; j < 4;j++)

dp[i][j] = oo;

//dp[0][0] = oo;

for (int i = 0; i < 4;i++)}}

} // cout << dp[3][3] << endl;

for (int i = 0; i< 4;i++)

cout << endl;

}}

案例3:

給定陣列arr,返回arr的最長遞增子串行的長度,比如arr=[2,1,5,3,6,4,8,9,7],最長遞增子串行為[1,3,4,8,9]返回其長度為5.

分析:

首先生成dp[n]的陣列,dp[i]表示以必須arr[i]這個數結束的情況下產生的最大遞增子串行的長度。對於第乙個數來說,很明顯dp[0]為1,當我們計算dp[i]的時候,我們去考察i位置之前的所有位置,找到i位置之前的最大的dp值,記為dp[j](0=

#include #include using namespace std;

/*動態規劃表*/

int dp[5] = {};

int main();

dp[0] = 1;

const int oo = 0;

for (int i = 1;i<5;i++)

int maxlist=0;

for (int i = 0; i < 5;i++)

if (dp[i] > maxlist)

maxlist=dp[i];

cout << maxlist << endl;

}

案例四:

給定兩個字串str1和str2,返回兩個字串的最長公共子串行,例如:str1="1a2c3d4b56",str2="b1d23ca45b6a","123456"和"12c4b6"都是最長公共子串行,返回哪乙個都行。

分析:本題是非常經典的動態規劃問題,假設str1的長度為m,str2的長度為n,則生成m*n的二維陣列dp,dp[i][j]的含義是str1[0..i]與str2[0..j]的最長公共子串行的長度。

dp值的求法如下:

dp[i][j]的值必然和dp[i-1][j],dp[i][j-1],dp[i-1][j-1]相關,結合下面的**來看,我們實際上是從第1行和第1列開始計算的,而把第0行和第0列都初始化為0,這是為了後面的取最大值在**實現上的方便,dp[i][j]取三者之間的最大值。

int findlcs(string a, int n, string b, int m) ;

for (int i = 0;i < n;i++)

因此,對於dp矩陣來說,行數是物品的數量n,列數是揹包的重量w,從左到右,從上到下,依次計算出dp值即可。

#include #include #include #include using namespace std;

int main();

int w[4] = ;

/*二維動態規劃表*/

vectorp(cap+1,0);

vector> dp(n+1,p);

for (int i = 1;i <=n;i++)

} cout << dp[n][cap] << endl;

}

案例6:

給定兩個字串str1,str2,在給定三個整數ic,dc,rc,分別代表插入,刪除和替換乙個字元的代價。返回將str1

編輯成str2的代價,比如,str1="abc",str2="adc",ic=5,dc=3,rc=2,從str1到str2,將'b'換成'd'代價最小,所以返回2.

分析:在構建出動態規劃表的時候,關鍵是搞清楚每個位置上數值的**。首先我們生成dp[m+1][n+1]的動態規劃表,m代表str1的長度,n代表str2的長度,那麼dp[i][j]就是str1[0..i-1]變成str2[0...j-1]的最小代價,則dp[i][j]的**分別來自以下四種情況:

a、首先將str1[i-1]刪除,變成str1[0...i-2],然後將str1[0...i-2]變成str2[0...j-1],那麼dp[i-1][j]就代表從str1[0..i-2]到str2[0...j-1]的最小代價,所以:dp[i][j] = dp[i-1][j]+dc;

b、同理也可以是從str1[0...i-1]變成str2[0...j-2],然後在插入str2[j-1],dp[i][j-1]就代表從str1[0...i-1]變成str2[0...j-2]的最小大家,所以:dp[i][j] = dp[i][j-1]+ic;

c、如果str[i-1] == str2[j-1],則只需要將str1[0...i-2]變成str2[0...j-2],此時dp[i][j] = dp[i-1][j-1];

d、如果str1[i-1]!=str2[j-1],則我們只需要將str1[i-1]替換成str2[j-1],此時dp[i][j] = dp[i-1][j-1]+rc;

在這四種情況當中,我們選取最小的乙個,即為最小代價。

#include #include #include #include using namespace std;

int main();

int ic=5,dc=3,rc=2;

//int ic = 1,dc=1,rc=1;

dp[0][0] = 0;

for (int i = 1;i

動態規劃演算法經典例題 動態規劃的經典模型

動態規劃演算法的核心就是記住已經解決過的子問題的解。記住求解的方式有兩種 自頂向下的備忘錄法 自底向上。線性模型的是動態規劃中最常用的模型,上文講到的鋼條切割問題就是經典的線性模型,這裡的線性指的是狀態的排布是呈線性的。例題1 是乙個經典的面試題,我們將它作為線性模型的敲門磚。例題1 在乙個夜黑風高...

動態規劃演算法經典問題 爬樓梯

我們用動態規劃方法解決日常生活中經常遇到的乙個問題 爬樓梯問題。一 問題描述 小明家住在二樓,每次回家都需要經過乙個10層台階的樓梯,小明每次可以選擇一步走一級台階或者一步走兩級台階。請幫小明計算他從樓下到家一共有多少種走法?打個比方,小明可以選擇每次都走一級台階,那麼他回家一共需要走十步,這是其中...

動態規劃演算法 案例

動態規劃的關鍵點 一系列以空間換時間的演算法 解析 動態規劃的實現的關鍵在於能不能準確合理的用動態規劃表來抽象出 實際問題。在這個問題上,我們讓f n 表示走上n級台階的方法數。那麼當n為1時,f n 1,n為2時,f n 2,就是說當台階只有一級的時候,方法數是一種,台階有兩級的時候,方法數為2。...