1. 程式人生 > >最簡單的動態規劃題,木有之一

最簡單的動態規劃題,木有之一

動態規劃英文名為dynamic programming,其中pogramming指的是表格法,而非編寫計算機程式。

基本原理

動態規劃將問題分成若干個相互重疊的子問題,遞迴的求解子問題,儲存子問題的解,再將它們的解組合起來,求出原問題的解。實際操作中,記錄下子問題的結果,儲存在一個表格中,使得公共的子問題只需要計算一次。

最優子結構

問題的最優解由相關子問題的最優解組合而成,一個問題的最優解包含其子問題的最優解。

總結

  • 滿足“最優子結構”性質的問題才能用動態規劃法來解;
  • 寫出狀態轉移方程和邊界條件,則問題得解;

題目

下面是一個最簡單的動態規劃小題目,沒有之一。

有一座高度是10級臺階的樓梯,從下往上走,每跨一步只能向上1級或者2級臺階。求一共有多少種走法。

思考過程

當只剩最後一步就上到10級的時候,有幾種情況呢?
兩種:走了9級了 和 走了8級了
因此,狀態轉移方程是

F(n) = F(n-1) + F(n-2)

而邊界條件呢?

F(1) = 1
F(2) = 2

開始程式設計

方法-1 簡單遞迴

做了許多重複計算,時間複雜度太高,達到O(2^N)

方法-2 遞迴+快取

不再做重複計算,時間複雜度只有O(N)了,而空間複雜度也是O(N)

cache = dict()

def f(n): 
    if n < 1:
        return 0
    if n in [1,2]: 
        return n
        
    if cache.get(n) is not None:
        return cache[n]
    else:
        result = f(n-1) + f(n-2)
        cache[n] = result 
        return result
        
        
print(f(100))

方法-3 自底向上迭代法

時間複雜度還是O(N), 空間複雜度只有O(1)

int climbing_ways(int n) 
{
    if (n<1) return 0;
    if (n==1 || n==2) return n;
    
    int a=1, b=1, temp=0;
    for(int i=3; i<=n; ++i) {
        temp = a + b;
        a = b;
        b = temp;
    }
    return temp;
}

(完)