說到動態規劃就不得不提一下分治法。因爲動態規劃是分支法的提升和優化。
分治法中,在分支法中我們通常將問題分解成n個互相獨立的的大致一樣的子問題,通過求解子問題的解,來獲得原問題的解。
但是它有一個弊端。舉例說明:(斐波那契數列的遞歸算法)
public static int fanco(int n) {
System.out.println("fanco("+n+")");
if (n<=1) {
return 1;
}
return fanco(n-1)+fanco(n-2);
}
由上面的算法運行得知:當n取5時,運行結果如下,它會一直重複執行已經算過的值。分治法的時間複雜度就會成指數增長。動態規劃算法完美的解決了這個問題。
動態規劃算法: 通過把原問題分解爲相對簡單的互相不獨立的子問題的方式求解複雜問題的方法。它在算出一個子問題的解後,就會把子問題存起來,放到一個數據結構中。在算其他子問題時,首先判斷一下,是否已經存在解。用這種放法來減少計算量,避免在重複子問題的數目關於輸入的規模呈指數增長問題。所以動態規劃算法在查找有很多重疊子問題的情況的最優解時有效。
而且它一般會得到最優值。
斐波那契數列的自底向上動態規劃算法。
public static void fanco2(int n) {
int f0,f1,f2;
f0=f1=f2=1;
for (int i = 2; i <= n; i++) {
f2 = f0+f1;
f0 = f1;
f1 = f2;
}
System.out.println(f2);
}
動態規劃的一般步驟:
找出最優解的性質並刻畫其數據結構,即分析問題來觀察問題運用動態規劃算法的可行性。
遞歸的定義最優值,最終得到動態規劃方程
以自底向上的方式計算最有值,
根據最優值來得到最優解。
斐波那契數列的自頂向下的動態規劃算法:
static int temp[] = new int[1000];
public static int fanco3(int n) {
int t = 0;
if (temp[n] != 0 ) {
return temp[n];
}
if (n==0) t=0;
if (n==1) t=1;
if(n>1) t=fanco3(n-1)+fanco(n-2);
return temp[n]=t;
}
注:動態規劃一般會求出一個最優解。