动态规划算法介绍
文章目錄
- 1 動(dòng)態(tài)規(guī)劃算法介紹
- 1.1 引入
- 1.2 動(dòng)態(tài)規(guī)劃算法介紹
1 動(dòng)態(tài)規(guī)劃算法介紹
1.1 引入
首先看一個(gè)問(wèn)題:一共有n級(jí)臺(tái)階,每次可以1級(jí)或者2級(jí)臺(tái)階,總共有多少種上法?
啟發(fā)性思考:
分治法核心思想: 從上往下分析問(wèn)題,大問(wèn)題可以分解為子問(wèn)題,子問(wèn)題中還有更小的子問(wèn)題比如總共有 5 級(jí)臺(tái)階,求有多少種走法;由于機(jī)器人一次可以走兩級(jí)臺(tái)階,也可以走一級(jí)臺(tái)階,所以我們可以分成兩個(gè)情況:
- 機(jī)器人最后一次走了兩級(jí)臺(tái)階,問(wèn)題變成了“走上一個(gè) 3 級(jí)臺(tái)階,有多少種走法?”
- 機(jī)器人最后一步走了一級(jí)臺(tái)階,問(wèn)題變成了“走一個(gè) 4 級(jí)臺(tái)階,有多少種走法?”
我們將求 n 級(jí)臺(tái)階的共有多少種走法用 f(n) 來(lái)表示,則f(n) = f(n-1) + f(n-2);
由上可得 f(5) = f(4) + f(3);
f(4) = f(3) + f(2);
f(3) = f(2) + f(1);
邊界情況分析:
走一步臺(tái)階時(shí),只有一種走法,所以 f(1)=1
走兩步臺(tái)階時(shí),有兩種走法,直接走 2 個(gè)臺(tái)階,分兩次每次走 1 個(gè)臺(tái)階,所以 f(2)=2。
走兩個(gè)臺(tái)階以上可以分解成上面的情況,這符合我們講解的分治法的思想: 分而治之。
實(shí)現(xiàn)代碼如下:
#include <stdio.h> #include <stdlib.h>/*遞歸實(shí)現(xiàn)機(jī)器人臺(tái)階走法統(tǒng)計(jì) 參數(shù):n - 臺(tái)階個(gè)數(shù) 返回: 上臺(tái)階總的走法 */ int WalkCout(int n){if(n<0) return 0;if(n==1) return 1; //一級(jí)臺(tái)階,一種走法else if(n==2) return 2; //二級(jí)臺(tái)階,兩種走法else { //n 級(jí)臺(tái)階, n-1 個(gè)臺(tái)階走法 + n-2 個(gè)臺(tái)階的走法return WalkCout(n-1) + WalkCout(n-2);} }int main(void){for(int i=1; i<=6; i++){printf("%d 臺(tái)階共有 %d 種走法\n", i, WalkCout(i)); }system("pause");return 0; }但是,上面的代碼中存在很多重復(fù)的計(jì)算?
其實(shí)我們可以從下向上分析推斷問(wèn)題:
代碼實(shí)現(xiàn)如下:
這就是動(dòng)態(tài)規(guī)劃法 !
1.2 動(dòng)態(tài)規(guī)劃算法介紹
動(dòng)態(tài)規(guī)劃:
也是一種分治思想,但與分治算法不同的是,分治算法是把原問(wèn)題分解為若干子問(wèn)題,自頂向下,求解各子問(wèn)題,合并子問(wèn)題的解從而得到原問(wèn)題的解。動(dòng)態(tài)規(guī)劃也是自頂向下把原問(wèn)題分解為若干子問(wèn)題,不同的是,然后自底向上,先求解最小的子問(wèn)題,把結(jié)果存儲(chǔ)在表格中,在求解大的子問(wèn)題時(shí),直接從表格中查詢小的子問(wèn)題的解,避免重復(fù)計(jì)算,從而提高算法效率。
什么時(shí)候要用動(dòng)態(tài)規(guī)劃?
如果要求一個(gè)問(wèn)題的最優(yōu)解(通常是最大值或者最小值),而且該問(wèn)題能夠分解成若干個(gè)子問(wèn)題,并且小問(wèn)題之間也存在重疊的子問(wèn)題,則考慮采用動(dòng)態(tài)規(guī)劃。
怎么使用動(dòng)態(tài)規(guī)劃?
五步曲解決:
參考資料:
總結(jié)