1. 程式人生 > >九章演算法4:動態規劃I

九章演算法4:動態規劃I

遞迴和動態規劃

從Triangle這個問題說起:

題目:

Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.
Example:
Given the following triangle:
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11).

三種解法

遇到這道題,老師說開始先給出暴力解法之後進行優化是可以的,不一定一開始就給出最優解,想出來一個暴力解法覺得傻就不說話。。。
- DFS:Traverse
DFS:Traverse
其中時間複雜度為O(2n), 其中n為Triangle中的點數, 注意使用Traverse的方法的時候,結果是當作函式引數傳遞的。
- DFS:Divide and Conquer
這裡寫圖片描述
時間複雜度依然為O(2n), 其中n為Triangle中的點數,同使用Traverse的方法不同的是,Divide and Conquer 的結果是作為函式返回值而不是函式引數,要不然沒法conquer。
-DFS:Divide and Conquer 加 memorization


這裡寫圖片描述
時間複雜度為O(n2),其中n為Triangle的層數。
其中注意,如果求最小值的時候,初始化往往是int或其型別的最大值;反之如果求最大值,初始化往往為最小值
記憶法的分治時間複雜度計算:

a=
b=
c=
=abc

此題中的時間複雜度的a為O(n2), b和c均為O(1), 最後的結果為O(n2)

討論:

動態規劃和分治

1.動態規劃是一種演算法思想,是高於演算法的.而分治的記憶化搜尋是實現動態規劃的一種手段.
2.那麼什麼是動態規劃呢?
-就感覺上來說,動態規劃的是"一層一層來",基於前一個狀態推出現在的狀態.
3.動態規劃為什麼會快呢?
-因為減少了很多不必要的重複計算.
4.動態規劃和分治的區別?
-動態規劃約等於分治+記憶化,因為有了記憶化,所以算過的直接用就行,就不用再算一遍了.

什麼時候使用動態規劃:

動態規劃適合把暴力時間複雜度為指數型的問題轉化為多項式的複雜度,即O(2n)O(n!) 轉化為O(n2)
1.求最大最小的問題
2.判斷可不可行,存不存在
3.統計方案個數

什麼時候不用動態規劃:

動態規劃不適合把本來時間複雜度就在O(n2)或者O(n3)的問題繼續優化,因為不怎麼能優化…
1.求!!所有的,具體的!!方案而不是方案個數,要用DFS而不是DP.(100%不用DP)
2.輸入資料是一個集合而非序列(90%不用DP)

動態規劃的實現方式

這裡寫圖片描述

多重迴圈的兩種方式:

  • 自底向上
  • 自頂向下

自底向上程式碼如下:
這裡寫圖片描述
時間複雜度: O(n2)
空間複雜度:O(n2),看開了一個多大的陣列就是結果,莫想的太複雜…
自頂向上程式碼如下:
這裡寫圖片描述
時間複雜度依舊: O(n2)
空間複雜度依舊:O(n2),依舊看開了一個多大的陣列就是結果,依舊莫想的太複雜…

動態規劃的四點要素

 1.狀態:即定義,劃分為六大問題
 2.方程:即從前一種狀態推出現在的狀態.
 3.初始化:極限小的狀態,即為起點.
 4.答案:終點

狀態的六大問題:

 1.座標型15%
 2.序列型30%
 3.雙序列型30%
 4.劃分型10%
 5.揹包型10%
 5.區間型5%

初始化的小技巧

 沒有左上和右上的提出來先算,也可以說成二維DP問題, [i,0]和[0,i]先初始化.

座標型動態規劃

這裡寫圖片描述