斐波納契數列f(n)
遞迴 vs 動態規劃
遞迴版本(太慢):
int f(int n)動態規劃版本(有效率!演算法複雜度是 o(n)):
int a[1000];構造乙個公式,它表示乙個問題的解是與它的子問題的 解相關的公式. e.g. f(n) = f(n-1) + f(n-2).int f(int n)
為這些子問題做索引 ,以便它們能夠在表中更好的儲存與檢索 (i.e., 陣列array)
以自底向上的方法來填寫這**; 首先填寫最小子問題的解.
這就保證了當我們解決乙個特殊的子問題時, 可以利用比它更小的所有可利用的 子問題的解.
演算法思想:
將待求解的問題分解成若干個子問題,並儲存子問題的解而避免計算重複的子問題,並由子問題的解得到原問題的解。
動態規劃演算法通常用於求解具有某種最優性質的問題。
動態規劃演算法的基本要素:最優子結構性質和重疊子問題。
原理:重疊子問題:在用遞迴演算法自頂向下解問題時,每次產生的子問題並不總是新問題,有些問題被反覆計算多次。對每個子問題只解一次,然後將其解儲存起來,以後再遇到同樣的問題時就可以直接引用,不必重新求解。
解決問題的基本特徵:
1. 動態規劃一般解決最值(最優,最大,最小,最長……)問題;
2. 動態規劃解決的問題一般是離散的,可以分解(劃分階段)的;
3. 動態規劃解決的問題必須包含最優子結構,即可以由(n-1)的最優推導出n的最優
解決問題的基本步驟:
動態規劃演算法的4個步驟:
1. 刻畫最優解的結構特性. (一維,二維,三維陣列)
2. 遞迴的定義最優解. (狀態轉移方程)
3. 以自底向上的方法來計算最優解.
4. 從計算得到的解來構造乙個最優解.
例題一. 斐波納契數列f(n)
步驟1:用f(n)表示在斐波納契數列中第n個數的值;
步驟2:狀態轉移方程:
步驟3:以自底向上的方法來計算最優解
nf(n)
步驟4:在陣列中分析構造出問題的解;
例題二. 輸入n,求出n!
步驟1:用f(n)表示n!的值;
步驟2:狀態轉移方程:
步驟3:以自底向上的方法來計算最優解
nf(n)
例題三:排隊買票問題
一場演唱會即將舉行。現有n個歌迷排隊買票,乙個人買一張,而售票處規定,乙個人每次最多只能買兩張票。假設第i位歌迷買一張票需要時間 ti(1≤i≤n),隊伍中相鄰的兩位歌迷(第j個人和第j+1個人)也可以由其中乙個人買兩張票,而另一位就可以不用排隊了,則這兩位歌迷買兩張票的時 間變為rj,假如rj分析:
如果前i個人買票的最優買票方式一確定,比如第i-1個人買一張票,則前i-1個人的買票方式也一定是最優的。即問題的最優解包含子問題的最優解。
步驟1:用f(i)表示前i個人買票的最優方式,即所需最短時間;現在要決定f(i)需要考慮兩種情況:
(1)第i個人的票自己買
(2)第i個人的票由第i-1個人買
步驟2:狀態轉移方程:
步驟3:以自底向上的方法來計算最優解
程式的實現(偽**):
buyticks(t, r)1 n ← length[t]
2 f[0] ← 0
3 f[1] ← t[1]
4for i ← 2 to n do
5 f[i] ← f[i-2]+r[i-1]
6if f[i] > f[i-1]+t[i] then
7 f[i] ← f[i-1]+t[i]
8return f
動態規劃演算法
一 動態規劃演算法原理 將待求解的問題分解成若干個相互聯絡的子問題,先求解子問題,然後從這些子問題的解得到原問題的解 對於重複出現的子問題,只在第一次遇到的時候對它進行求解,並把答案儲存起來。了不去求解相同的子問題,引入乙個陣列,把所有子問題的解存於該陣列中,這就是動態規劃所採用的基本方法。動態規劃...
動態規劃演算法
動態規劃 通過把原問題分解為相對簡單的子問題來求解複雜問題。動態規劃常常適用於有重疊子問題和最優子結構性質的問題。演算法總體思想 演算法的基本步驟 演算法的基本要素 最優子結構 重疊子問題 備忘錄方法 問題描述 子串行 公共子串行 最長公共子串行 lcs 問題 問題分析 動態規劃求解lcs問題 最長...
動態規劃演算法
動態規劃演算法的思路 動態規劃法即 dynamic programming method dp 是系統分析中的種常用方法。動態規劃法是20世紀50年代由貝爾曼 r.bellman 等人提出的,用來解決多階段決策過程問題的一種最優化方法。多階段決策過程是指把研究問題分成若干個相互聯絡的階段,由每個階段...