動態規劃一般用陣列記錄下每一步的最優值,返回最後一步的值就是最優結果,相對於遞迴解法消除了重複計算的部分,提高的效率。
計數:有多少種方式從a到b、多少種方式取得某值、、、
求最優解:最大值最小值、路徑上最大資料和。
存在性問題:能不能選出和為k的數、、、
選定演算法前一定要判斷是否為動態規劃解題、有時候問題相似但不能用動態規劃求解。
以leetcode 322 零錢兌換 為例:
給定不同面額的硬幣 coins 和乙個總金額 amount。
編寫乙個函式來計算可以湊成總金額所需的最少的硬幣個數。
如果沒有任何一種硬幣組合能組成總金額,返回 -1。
示例 1:
輸入: coins = [1, 2, 5], amount = 11
輸出: 3
解釋: 11 = 5 + 5 + 1
示例 2:
輸入: coins = [2], amount = 3
輸出: -1
說明:你可以認為每種硬幣的數量是無限的。
首先要確定狀態就是解決問題的最後一步和確定子問題。
由之前的結果寫出轉移方程
對於示例1:f(x)=min
對於示例1:
動態規劃一般都是以自底向上進行迴圈迭代計算,
而帶備忘錄的遞迴則是自頂向下進行計算。
在例題中:轉移方程計算左邊時,右邊的內容都需要已經有結果了
計算f(11)時需要f(10)、f(9)、f(6)的具體值,那麼從小到大計算(根據題目以及選定解題方式選定計算順序)。
最後是編碼,與理論不一樣,程式編碼中很多要注意的地方,如
public
intcoinchange
(int
coins,
int amount)}}
if(f[amount]
== integer.max_value)
return f[amount]
;}
例題
力扣 62.題不同路徑
乙個機械人位於乙個 m x n 網格的左上角 (起始點在下圖中標記為「start」 )。
機械人每次只能向下或者向右移動一步。機械人試圖達到網格的右下角(在下圖中標記為「finish」)。
問總共有多少條不同的路徑?
例如,上圖是乙個7 x 3 的網格。有多少可能的路徑?
示例 1:
輸入: m = 3, n = 2
輸出: 3
解釋:從左上角開始,總共有 3 條路徑可以到達右下角。
1. 向右 -> 向右 -> 向下
2. 向右 -> 向下 -> 向右
3. 向下 -> 向右 -> 向右
示例 2:
輸入: m = 7, n = 3
輸出: 28
1 <= m, n <= 100
題目資料保證答案小於等於 2 * 10 ^ 9
解題步驟:確定最後一步:到達右下角的路徑數。
確定子問題:到達當前格仔路徑數量=到達上面各自數量+到達左邊格仔數量。
做出轉移方程:f(x)(y)=f(x-1)(y)+f(x)(y-1)
確定初始條件和邊界:第一行和第一列每格到達路徑數都為1。
確定計算順序:計算當前格需要知道上面格仔與左邊格仔的路徑數量->從前往後。
編碼:
例題 63.不同路徑ⅱ
乙個機械人位於乙個 m x n 網格的左上角 (起始點在下圖中標記為「start」 )。
機械人每次只能向下或者向右移動一步。機械人試圖達到網格的右下角(在下圖中標記為「finish」)。
現在考慮網格中有障礙物。那麼從左上角到右下角將會有多少條不同的路徑?
網格中的障礙物和空位置分別用 1 和 0 來表示。
說明:m 和 n 的值均不超過 100。
示例 1:
輸入:[
[0,0,0],
[0,1,0],
[0,0,0]
]輸出: 2
解釋:3x3 網格的正中間有乙個障礙物。
從左上角到右下角一共有 2 條不同的路徑:
1. 向右 -> 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右 -> 向右
解題步驟:確定最後一步:到達右下角的路徑數。
確定子問題:到達當前格仔路徑數量=到達上面各自數量+到達左邊格仔數量(前提為計算的格仔都不包含障礙物)。
做出轉移方程:f(x)(y)(不是障礙物)=f(x-1)(y)(不是障礙物)+f(x)(y-1)(不是障礙物)
確定初始條件和邊界:有障礙物就為0;第一格不是障礙物就為1。
確定計算順序:計算當前格需要知道上面格仔與左邊格仔的路徑數量->從前往後。
編碼:
例題 70.爬樓梯
假設你正在爬樓梯。需要 n 階你才能到達樓頂。
每次你可以爬 1 或 2 個台階。你有多少種不同的方法可以爬到樓頂呢?
注意:給定 n 是乙個正整數。
示例 1:
輸入: 2
輸出: 2
解釋: 有兩種方法可以爬到樓頂。
1. 1 階 + 1 階
2. 2 階
示例 2:
輸入: 3
輸出: 3
解釋: 有三種方法可以爬到樓頂。
1. 1 階 + 1 階 + 1 階
2. 1 階 + 2 階
3. 2 階 + 1 階
解題步驟:確定最後一步:到達樓頂
確定子問題:到達當前階層方法數量=前一層數量踏一步+上上層數量踏兩步。
做出轉移方程:f(x)=f(x-1)+f(x-2)
確定初始條件和邊界:第一層為1,第二層為2。
編碼:
不用陣列的話:
經典動態規劃學習記錄
動態規劃本質是一種用空間換時間的優化方法,通常來優化可以暴力搜尋求解的問題,也就是去冗餘,把之前計算過的存下來,而且是規定了遞迴的計算順序,從簡單基本的出發,依次計算 這也是他優於記憶搜尋的地方 方法大概如下 1.首先能明白暴力遞迴怎麼實現 重要 2.找到函式中可以代表遞迴過程的引數 3.引數為ke...
動態規劃學習
首先是01揹包問題,可以把它看做是乙個 行和列分別是體積從1,2,v,每個物品的花費c1,c2,cn,每個空格裡的數代表放入第i個物品在體積為j的揹包裡的最大價值。dp j 表示體積為j的揹包,放入物品後,可以得到的最大值。狀態轉移方程為if j c i dp j max dp j dp j c i...
動態規劃學習
把位置 i,j 看成乙個狀態,然後定義狀態 i,j 的指標函式d i,j 從位置 i,j 出發時能得到的最大和。int i,j 邊界值處理 for j 1 j n j result n j data n j 由下向上動態規劃,儲存葉子節點到當前節點的最大值 for i n 1 i 1 i for j...