動態規劃是為了解決遞迴呼叫佔記憶體、時間複雜度較大人的問題,而提出的一種程式設計思想。其中較為經典的,則是解決了斐波那契數列的低計算效率問題。
若是運用遞迴呼叫去求斐波那契數列的第n位數,則按照此方法,會將該位數根據公式,拆分成其他兩位數。而將其拆分出來的兩位數則會繼續被拆分為更小的兩位數,直到拆分到數列的開頭兩位已知數值的斐波那契數。可是,問題就在於,如果一直這樣拆分下去,原本早在樹的另一分支下被求出的數,因為沒有被儲存下來,以至於做著重複計算的低效率工作,大大拖延了程式執行時間。
到這裡,大家已經想到了問題的解決方法——將已經求過的數通過陣列儲存起來, 該方法被稱為備忘錄法。
public class dp
// if (n == 1)
// return f(n - 1) + f(n - 2);
// }
// o為2的n次方
// /**
// * 注: 動態規劃(備忘錄法)
// * 即即將原來的計算過的值儲存下來
// * 即傳乙個陣列進來
// * @param n
// * @return
// */
// public static int f(int n,int bak)
// if (n == 1)
//
// if(bak[n] !=-1)
//
//
// //若第n個值沒有求過,則
// int result=f(n - 1,bak) + f(n - 2,bak);
// //不要忘記將備忘錄也傳進去
//
// bak[n]=result;
// //曾經計算過的值將其存起來
//
// return result;
// }
/*** 注: 自底向上
* @param n
* @return
*/public static int f(int n)
if (n == 1)
// if(bak[n] !=-1)
//
//
// //若第n個值沒有求過,則
// int result=f(n - 1,bak) + f(n - 2,bak);
// //不要忘記將備忘錄也傳進去
//
// bak[n]=result;
// //曾經計算過的值將其存起來
// return result;
// }
// //雖然降低了複雜度,但用的仍是遞迴
int result=0;
int r1 =1;
int r2 =1;
for(int i=2;i<=n;i++)
return result;
} public static void main(string args)
// system.out.println(f(n,bak));
system.out.println(f(n));
}}
我們在這裡可以看出,該方法的注意點就在於——要將備忘錄傳進去,並且要給備忘錄裡的陣列初始化值為-1。這裡,乙個是要在數列的計算過程中將已經計算的值存入備忘錄中,另乙個則是要判斷我們所要求的數是否在數列之中。同時,返回值中判斷有了底n個數的值之後,也就不用再計算下去了。 動態規劃初識
適合用動態規劃的問題特徵 可以分解成相互重疊的若干子問題 滿足最優性原理 結構性質 該問題的最優解中也包含著其子問題的最優解。一般地,子問題的聯絡體現在某種遞推關係,通過這種遞推計算可以把問題的解儲存起來,後期直接使用,避免重複運算。簡單的dp例子 遞推關係 m i j m i 1 j m i j ...
初識動態規劃
有乙個矩陣map,它每個格仔有乙個權值。從左上角的格仔開始每次只能向右或者向下走,最後到達右下角的位置,路徑上所有的數字累加起來就是路徑和,返回所有的路徑中最小的路徑和。給定乙個矩陣map及它的行數n和列數m,請返回最小路徑和。保證行列數均小於等於100.輸入輸出樣例 第一行,輸入n,m表示這個矩陣...
初識動態規劃
let maxw 0 最大可放重量 let weight 2 2,4 6,3 物品重量 let n weight.length let w 11 揹包最大可承受重量 let men for let i 0 i n i men.push f 0,0 11 function f i,cw f i 1,c...