動態規劃學習筆記(1)

2021-10-02 15:11:18 字數 4561 閱讀 4388

記錄一下慕課學習的筆記,以及例題**

遞迴函式有n個引數就定義乙個n維的陣列, 陣列的下標是遞迴函式引數的取值範圍。

這樣就可以從邊界值開始逐步填充陣列,相當於計算遞迴函式值的逆過程。eg:例題1數字三角形

1.將原問題分解為子問題

將原問題分解為若干個子問題,與原問題的形式相同或類似,只不過規模小了。

子問題都解決,原問題即解決。

子問題的解一旦求出就會被儲存,所以每個子問題只要求解一次。

2.確定狀態

狀態:往往把和子問題相關的各個變數的一組取值稱為乙個狀態。乙個狀態對應於乙個或多個子問題。

:所謂某個狀態下的值就是這個狀態所對應的子問題的解。

時間複雜度:整個問題的時間複雜度是狀態數目乘以每個狀態所需時間。

儲存:若k個整型變數能夠構成乙個狀態,且取值範圍分別為n1,n2,……,nk,我們就可以用乙個k維的陣列array[n1][n2]……[nk]來儲存各個狀態的「值」,這個值未必是乙個整數或浮點數,甚至可能是需要乙個結構表示的,故array可以是乙個結構陣列。

3.確定一些初始狀態(邊界狀態)的值

4.確定狀態轉移方程

定義出什麼是狀態,以及在該狀態下的值後,就要找出不同的狀態之間如何遷移。

如何從乙個或多個值已知的狀態推出另乙個狀態的值(「人人為我"遞推型)。狀態的遷移可以用遞推公式表示,此遞推公式也可稱作"狀態轉移方程」。

1)問題具有最優子結構性質

最優子結構性質:如果問題的最優解所包含的子問題的解也是最優的,稱其具有該性質。

2)無後效性

當前的若干個狀態值一旦確定,則此後過程的演變就只和這若干個狀態的值有關,與之前是採取哪種手段或經過哪條路徑演變到當前這若干個狀態無關。

例題1.數字三角形

題意

:給定乙個由n行數字組成的數字三角形如下圖所示。試設計乙個演算法,計算出從三角形的頂至底的一條路徑,使該路徑經過的數字總和最大。

對於給定的由n行數字組成的數字三角形,計算從三角形的頂至底的路徑經過的數字和的最大值。

輸入資料的第1行是數字三角形的行數n,1≤n≤100。接下來n行是數字三角形各行中的數字。所有數字在0…99之間。

輸出資料只有乙個整數,表示計算出的最大值。

示例輸入

5

73 8

8 1 0

2 7 4 4

4 5 2 6 5

示例輸出

**1 記憶遞迴型動歸程式

#include

#include

#define max 101

using

namespace std;

//用遞迴的話會超時 重複計算太多

//所以將每次遞迴的結果算出來存到陣列裡

//叫做記憶遞迴型動歸程式

int d[max]

[max]

;//d[r][j]表示第r行第j個數字(r,j從1開始算)

int maxsum[max]

[max]

;//從d(r,j)到底邊的各條路徑中,最佳路徑的數字之和

int n;

intmaxsum

(int i,

int j)

return maxsum[i]

[j];

}int

main()

} cout <<

maxsum(1

,1)<< endl;

return0;

}

**2 迴圈 遞推式 動態規劃

#include

#include

#define max 101

using

namespace std;

//迴圈 遞推式 動態規劃

int d[max]

[max]

;//d[r][j]表示第r行第j個數字(r,j從1開始算)

int maxsum[max]

[max]

;//從d(r,j)到底邊的各條路徑中,最佳路徑的數字之和

int n;

intmain()

}for

(i =

1; i <= n; i++

) maxsum[n]

[i]= d[n]

[i];

for(i = n-

1; i >=

1; i--)}

cout << maxsum[1]

[1]<< endl;

return0;

}

例題2.神奇的口袋

題意

有乙個神奇的口袋,總的容積是40,用這個口袋可以變出一些物品,這些物品的總體積必須是40。john現在有n個想要得到的物品,每個物品的體積分別是a1,a2……an。john可以從這些物品中選擇一些,如果選出的物體的總體積是40,那麼利用這個神奇的口袋,john就可以得到這些物品。現在的問題是,john有多少種不同的選擇物品的方式。

輸入輸出

輸入:320

2020

輸出:3

**

#include

#include

#include

using

namespace std;

int a[30]

;int n;

int ways[40]

[30];

//ways[i][j]表示從j種物品裡湊出體積i的方法數

intmain()

ways[0]

[0]=

1;for(

int w =

1; w <=

40; w++)}

cout << ways[40]

[n];

return0;

}

例題3.最長公共子串行

題意

給出兩個字串求乙個最長的公共子串行的長度

輸入輸出

輸入:

abcfbc abfcab

programming contest

abcd mnp

輸出:420

**

#include

#include

#include

#include

using

namespace std;

int dp[

1001][

1001];

/*思路:設dp(i,j)表示s1左邊i個字元形成的子串

與s2左邊j個字元形成的字串的最長公共子串行的長度

dp(n,0) = 0, dp(0,n) = 0;

if (s1[i-1] == s2[j-1]) dp(i,j) = dp(i-1,j-1) + 1;

else dp(i, j) = max(dp(i,j-1), dp(i-1,j));*/

intmain()

} cout << dp[len1]

[len2]

<< endl;

return0;

}

例題4.最長上公升子串行

題意

輸入第一行序列的長度n,第二行n個整數

輸出最長上公升子串行的長度

輸入輸出

輸入樣例:

71 7 3 5 9 4 8

輸出樣例:

4

**

#include

#include

using

namespace std;

const

int maxn =

1010

;/*思路:分解為求以ak為終點的最長上公升子串行的長度 ,maxlen(k)表示以ak為終點的最長上公升子串行長度

為在ak左邊 且ai小於ak 長度最大的最長上公升子串行的長度+1

因為ak左邊任何終值小於ak的子串行加上ak後就能形成乙個更長的上公升子串行*/

int a[maxn]

;int maxlen[maxn]

;int

main()

for(

int i =

2; i <= n; i++)}

}for

(int i =

1; i <= n; i++

) cout << ans << endl;

return0;

}//時間複雜度o(n^2)

**慕課程式設計與演算法(二)動態規劃 ppt

動態規劃筆記1

力扣的零錢兌換問題 給定不同面額的硬幣 coins 和乙個總金額 amount。編寫乙個函式來計算可以湊成總金額所需的最少的硬幣個數。如果沒有任何一種硬幣組合能組成總金額,返回 1。示例 1 輸入 coins 1,2,5 amount 11 輸出 3 解釋 11 5 5 1 示例 2 輸入 coin...

學習筆記 動態規劃

動態規劃 多階段決策 意義 求解決策過程最優化的數學方法 基本思想 將待求解的問題分為若干個階段,即若干個互相聯絡的子問題,在求解子問題的過程中逐步推導出原問題的解。核心 在求解子問題的過程中,儲存子問題的解。注1 動態規劃的思想實際上和遞迴相似。都是通過逐步推導,得到答案。而用它們解題時的核心也都...

學習筆記 動態規劃

bullet 先來看乙個問題 小張現在有8個任務可選,每個任務都必須在規定的時間段完成不能多也不能少,而且每個任務都有對應的報酬如下圖,問小張應如何選擇才能拿到最多的報酬?那我們換種方法來解決這個問題吧,首先,每個任務都有選和不選兩種選擇,我們從最後乙個任務開始模擬這個過程。首先我們需要先用乙個陣列...