初闻动态规划
前言
本文以一道常見的算法面試題開篇,引入動(dòng)態(tài)規(guī)劃的基礎(chǔ)概念, 介紹其思考過程。
正文
一、常見的一道算法面試題——上臺(tái)階
有一個(gè)樓梯總共n個(gè)臺(tái)階,只能往上走,每次只能上1個(gè)、2個(gè)臺(tái)階,總共有多少種走法。
解決方案:
1、排列組合;
枚舉2的個(gè)數(shù),再枚舉2具體放的位置;
計(jì)算復(fù)雜,容易遺漏。
2、動(dòng)態(tài)規(guī)劃;
dp[n] 表示n個(gè)臺(tái)階的走法,那么有:
dp[n]=dp[n-1]+dp[n-2];
思路清晰,代碼簡(jiǎn)單。
二、動(dòng)態(tài)規(guī)劃基礎(chǔ)概念
1、動(dòng)態(tài)規(guī)劃;
動(dòng)態(tài)規(guī)劃(Dynamic Programming)指的是解最優(yōu)化問題的一種方法。
2、最優(yōu)子結(jié)構(gòu)性質(zhì);
問題的最優(yōu)解可以分解為若干子問題,且子問題的解也是最優(yōu)的;
以上臺(tái)階為例,到第i層的最多走法,可以分解為第i-1層和第i-2層的走法之和,且第i-1層和第i-2層的走法也是最多的;
3、 無后效性;
現(xiàn)階段的決策不會(huì)影響未來的決策;
以上臺(tái)階為例,走到第i-2層的最多走法,不會(huì)因?yàn)樵黾拥趇-1層而改變;
三、動(dòng)態(tài)規(guī)劃思考過程
動(dòng)態(tài)規(guī)劃的思考過程可以總結(jié)為:大事化小,小事化了。
大事化小:
一個(gè)較大的問題,通過找到與子問題的重疊,把復(fù)雜的問題劃分為多個(gè)小問題,也稱為狀態(tài)轉(zhuǎn)移;
小事化了:
小問題的解決通常是通過初始化,直接計(jì)算結(jié)果得到;
具體的步驟
1、將大問題分解為子問題
2、確定狀態(tài)表示
3、確定狀態(tài)轉(zhuǎn)移
4、考慮初始狀態(tài)和邊界情況
四、另一個(gè)經(jīng)典的例子——數(shù)塔
有如圖所示的數(shù)塔,要求從頂層走到底層,若每一步只能走到相鄰的結(jié)點(diǎn),則經(jīng)過的結(jié)點(diǎn)的數(shù)字之和最大是多少?
解決思路:
1、大事化小。要到達(dá)第i層,先要到達(dá)第i-1層。并且第i層的第j個(gè)節(jié)點(diǎn),只能由i-1層的第j個(gè)和第j-1個(gè)節(jié)點(diǎn)到達(dá)。
我們用dp[i][j]表示,走到第i層第j個(gè)位置的數(shù)字最大和。
那么有dp[i][j]=max(dp[i-1][j], dp[i-1][j-1]) + a[i][j];
2、小事化了。第1層的第1個(gè)節(jié)點(diǎn),初始值為dp[1][1]=a[1][1]。(a[x][y]表示第x層,第y個(gè)的值)
五、數(shù)塔例子的變形——收集蘋果
平面上有N*M個(gè)格子,每個(gè)格子中放著一定數(shù)量的蘋果。
你從左上角的格子開始,每一步只能向下走或是向右走,每次走到一個(gè)格子上就把格子里的蘋果收集起來。這樣下去,你最多能收集到多少個(gè)蘋果。
解決思路:
1、只能向右走或者向下走,要到達(dá)第i行第j列的格子的時(shí)候,可以由第i-1行第j列或者第i行第j-1列到達(dá),我們用dp[i][j]表示,走到第i行第j列的最多蘋果數(shù),那么有:
dp[i][j]=max(dp[i-1][j], dp[i][j-1]) + a[i][j];
2、第1行第1列,初始值為dp[1][1]=a[1][1],注意事項(xiàng)是邊界條件的處理。
六、動(dòng)態(tài)規(guī)劃經(jīng)典——01背包問題
給定n件物品和一個(gè)容量為m的背包,每件物品都會(huì)消耗背包的一定容積c[i],并帶來一定價(jià)值v[i],要求如何選取裝入背包中的物品,使得背包內(nèi)的物品價(jià)值最大。
解決思路:
把n件物品放入背包,可以分解為“將前i件物品放入容量為m的背包中”問題。
若只考慮第i件物品的選擇,那么問題可以分為兩種情況:
1、如果不放第i件物品,問題就轉(zhuǎn)化為“前i-1件物品放入容量為v的背包中”;
2、如果放第i件物品,問題就轉(zhuǎn)化為“前i-1件物品放入剩下的容量為m-c[i]的背包中”;
我們用f[i][j]表示前i個(gè)物品,放入容量為j的背包的最大價(jià)值,上面的兩種情況可以表示為
f[i][j] = max(f[i-1][j], f[i-1][j-c[i]]+v[i]);
初始化條件memset(dp, 0, sizeof(dp));和dp[1][c[1]]=v[1]。
最后遍歷f[n][1~m]可以得到最大值。
總結(jié)
如果還不能完全理解01背包,那么還需要再仔細(xì)理解最優(yōu)子結(jié)構(gòu)、狀態(tài)表示和狀態(tài)轉(zhuǎn)移。
算法能擴(kuò)展思考方向,完善思維能力。學(xué)會(huì)“上臺(tái)階”、“數(shù)塔”、“01背包”這三個(gè)題目,能解決算法面試的動(dòng)態(tài)規(guī)劃部分。
參考及引用
程序員算法基礎(chǔ)——?jiǎng)討B(tài)規(guī)劃
總結(jié)
- 上一篇: 火狐浏览器添加MetaMask钱包和本地
- 下一篇: svm分类器训练详细步骤_「五分钟机器学