演算法學習08 動態規劃

2021-09-12 18:31:08 字數 4182 閱讀 4578

遞迴問題

暴力遞迴轉換成動態規劃

動態規劃本身就是暴力遞迴的優化,是一種用空間換時間的策略

動態規劃:

我們不知道怎麼計算n!,但我們知道:

n!(n-1)!之間存在一定關係n!=n*(n-1)!,得到遞推的狀態轉移公式.

當暴力遞迴到頭得到0!=1,得到base case,這樣得到了遞迴的方法.

public

static

long

getfactorial1

(int n)

return

(long

) n *

getfactorial1

(n -1)

;}

將遞推反過來考慮,從base case出發,可以得到遞推方法:

public

static

long

getfactorial2

(int n)

return result;

}

問題: 不能大壓小,只能小壓大,每次只能移動乙個圓盤.最終借助help堆將n層圓盤從from堆移動到to堆. 列印n層漢諾(最上面為第1層,最下面為第n層)塔從from移動到to的全部過程

思路:

先來**將第[1~n]層from移動到to的過程:

先把第[1~(n-1)]層from移動到help上.

再把單獨的第n層移從from移動到to上.

再把第[1~n-1]層help移動到到to上.

這三步中第1步第3步都是將規模縮小了的子問題,這樣得到了狀態轉移公式.

這裡我們**第[1~n]層時,大於n層的所有圓盤都應該在這些盤子以下,因此絕對不會出現小壓大的情況.

下面我們尋找base case: 容易想到,當漢諾塔只有一層時,可以不借助help,直接將該層從from移動到to

由此得到其遞迴**如下:

public

class

hanoi

else

}public

static

void

main

(string[

] args)

}

輸出3層漢諾塔的移動過程如下:

將第1層盤子從左堆移動到中堆

將第2層盤子從左堆移動到右堆

將第1層盤子從中堆移動到右堆

將第3層盤子從左堆移動到中堆

將第1層盤子從右堆移動到左堆

將第2層盤子從右堆移動到中堆

將第1層盤子從左堆移動到中堆

暴力遞迴:

狀態轉移公式: 對於字串中每個字元每個字元可以選擇要或不要,

base case: 判斷完最後乙個字串就可以輸出了.

暴力遞迴:

狀態轉移公式: 每一位的字元都可以跟自己及其後面任意乙個字元相交換

base case: 判斷完最後乙個字串就可以輸出了.

暴力遞迴方法會導致大量狀態被重複計算,而動態規劃通過記憶這些狀態的值,避免了重複計算,是一種用空間換時間的策略.

有一類問題能從暴力遞迴轉換為動態規劃,被稱作無後效性問題.

問題: 給出乙個二維陣列,要求返回從左上角到右下角的最小路徑和.

暴力遞迴:

walk(int i, int j)函式返回某點到右下角的最小路徑和

題目: 給你乙個陣列arr和乙個整數aim. 任意選擇arr中的數字,能否累加得到aim.

暴力遞迴: 類似子串行問題,每個數字都可以選擇要或者不要.

issum(判斷到的index, 前邊的累加和sum)函式返回陣列[0~index]區間內是否能累加成目標aim.

狀態轉移方程: 若[0~index-1]之間選擇數字能達到aim-arr[index],則[0~index]一定能選擇數字達到aim; 否則不能達到aim.即issum(index, sum) = issum(index-1, sum-arr[index]).

base case:index=陣列長度表示判斷完整個陣列的結果,因此判斷其前向累加和是否為aim填表. 且不論index為多少,前向累加和若為aim,則返回true.

動態規劃:

設想如下數字序列:,判斷完前三個數字時,是選擇還是選擇,前邊的累加和都是一樣的,不影響後邊判斷.

因為從[0~index]之間選擇具體哪幾個數字達到aim與 後面選擇無關,因此是乙個無後效性問題,可以用動態規劃.

base case,即index=len開始,向index減小方向遞推,直到遞推到並返回issum(0,0).

**如下:

public

static

boolean

money2

(int

arr,

int aim)

// 按判斷的index從arr.length到0遞減填表

for(

int i = arr.length -

1; i >=

0; i--)}

}// 結果應返回: 最開始選擇0個數,且初始累加和為0時的結果

return issum[0]

[0];

}

推廣: 考慮陣列成員存在負數的情況,若陣列成員有負數,則前向累加和可能為負數,因此所填的表的橫座標可能為負數. 實際編碼過程中,給累加和項加乙個偏移,偏移量為累加和可能的最小負數.

這類問題與k-sum問題的區別: k-sum問題為有後效性問題,因為要求只能選取k個數,所以在記錄累加和的同時要考慮已經選取了幾個數.

給定兩個陣列w和v,兩個陣列長度相等,w[i]表示第i件商品的重量,v[i]表示第i件商品的價值。 再給定乙個整數bag,要求你挑選商品的重量加起來一定不能超 過bag,返回滿足這個條件下,你能獲得的最大價值。

演算法學習 動態規劃

動態規劃是解決多階段決策過程最優化的一種方法。對於離散問題,解析數學無法施展,動態規劃則成為非常有效的工具。兩個弱點 1.得出目標函式方程後,尚無統一的處理方法,必須根據具體問題的性質結合相應的數學技巧來求解 2.維數障礙。動態規劃模型的分類 根據決策過程的時間參量是離散的還是連續的變數 1.離散 ...

演算法學習 動態規劃實踐

完成日期 2017.10.26 1.實踐題目 數字三角形 2.問題描述 給定乙個由 n行數字組成的數字三角形如下圖所示。試設計乙個演算法,計算出從三角形 的頂至底的一條路徑 每一步可沿左斜線向下或右斜線向下 使該路徑經過的數字總和最大。3.演算法描述 1 首先該問題有最優子結構和重疊子問題的性質,因...

演算法學習(十)動態規劃!!!

1.先上一波官方解讀提提神 動態規劃 英語 dynamic programming,簡稱dp 是一種在數學 管理科學 電腦科學 經濟學和生物資訊學中使用的,通過把原問題分解為相對簡單的子問題的方式求解複雜問題的方法。動態規劃常常適用於有重疊子問題和最優子結構性質的問題。官方術語太多?不能理解?wha...