1. 程式人生 > >動態規劃——DP算法(Dynamic Programing)

動態規劃——DP算法(Dynamic Programing)

最優 n) 每次 for 利用 列表 自底向上 python bubuko

一、斐波那契數列(遞歸VS動態規劃)

技術分享圖片

1、斐波那契數列——遞歸實現(python語言)——自頂向下

遞歸調用是非常耗費內存的,程序雖然簡潔可是算法復雜度為O(2^n),當n很大時,程序運行很慢,甚至內存爆滿。

1 def fib(n):
2     #終止條件,也就是遞歸出口
3     if n == 0 or n == 1:
4         return 1
5     else:
6         #遞歸條件
7         return (fib(n-1) + fib(n - 2))

2、斐波那契數列——動態規劃實現(python語言)——自底向上

動態規劃——將需要重復計算的問題保存起來,不需要下次重新計算。對於斐波那契數列,算法復雜度為O(n)。

1 def dp_fib(n):
2     #初始化一個數組,用於存儲記錄計算的結果。
3     res = [None] * (n + 1)
4     #前兩項設置為1。
5     res[0] = res[1] = 1
6     #自底向上,將計算結果存入數組內。
7     for i in range(2, (n + 1)):
8         res[i] = res[i-1] + res[i-2]
9     return
res[n]

3、方法概要

  (1)構造一個公式,它表示一個問題的解是與它的子問題的解相關的公式:

     技術分享圖片

  (2)為這些子問題做索引,以便於它們能夠在表中更好的存儲與檢索(用數組存儲)。

  (3)以自底向上的方法來填寫這個表格;首先填寫最小的子問題的解。

  (4)這就保證了當我們解決一個特殊的子問題時,可以利用比它更小的所有可利用的子問題的解。

總之,因為在上世紀40年代(計算機普及很少時),這些規劃設計是與“列表”方法相關的,因此被稱為動態規劃——Dynamic Programing。

二、動態規劃算法——思想簡介

1、DP算法思想

  (1)將待求解的問題分解稱若幹個子問題,並存儲子問題的解而避免計算重復的子問題,並由子問題的解得到原問題的解。

   (2)動態規劃算法通常用於求解具有某種最有性質的問題。

   (3)動態規劃算法的基本要素:最優子結構性質和重疊子問題。

      最優子結構性質:問題的最優解包含著它的子問題的最優解。即不管前面的策略如何,此後的決策必須是基於當前狀態(由上一次的決策產生)的最優決策。

      重疊子問題:在用遞歸算法自頂向下解問題時,每次產生的子問題並不總是新問題,有些問題被反復計算多次。對每個子問題只解一次,然後將其解保存起來,

            以後再遇到同樣的問題時就可以直接引用,不必重新求解。

2、DP算法——解決問題的基本特征

  (1)動態規劃一般求解最值(最優、最大、最小、最長)問題;

   (2)動態規劃解決 的問題一般是離散的,可以分解的(劃分階段的)。

   (3)動態規劃結局的問題必須包含最優子結構,即可以有(n-1)的最優推導出n的最優。

3、DP算法——解決問題的基本步驟

  動態規劃算法的四個步驟:

    (1)刻畫最優解的結構特性。(一維、二維、三維數組);

    (2)遞歸的定義最優解。(狀態轉移方程)

    (3)以自底向上的方法來計算最優解。

    (4)從計算得到的解來構造一個最優解。

4、求解例子——求階乘 n!

技術分享圖片

技術分享圖片

 1 #遞歸實現求階乘
 2 def multiply(n):
 3     if n == 0 or n == 1:
 4         return 1
 5     return n * multiply(n -1)
 6 
 7 
 8 #動態規劃實現求階乘
 9 def dp_multiply(n):
10     temp = [None] * (n + 1)
11     temp[0] = 1
12     temp[1] = 1
13     for i in range(2, n + 1):
14         temp[i] = i * temp[i - 1]
15     return temp[n]

動態規劃——DP算法(Dynamic Programing)