動態規劃法

2021-09-21 07:21:39 字數 1434 閱讀 5183

動態規劃的關鍵點

動態規劃演算法的兩種形式

舉乙個簡單的例子:就斐波拉契數列fibonacci

fibonacci (n) = 1;   n = 0

fibonacci (n) = 1; n = 1

fibonacci (n) = fibonacci(n-1) + fibonacci(n-2)

一、首先使用遞迴版本實現這個演算法

public int fib(int n)

//輸入6

//輸出:8

分析遞迴演算法的執行流程,輸入6,執行的遞迴樹如圖所示

上面的遞迴樹中的每乙個子節點都會執行一次,很多重複的節點被執行,fib(2)被重複執行了五次,由於呼叫每乙個函式的時候都要保留上下文,所以空間上開銷也不小。這麼多的子節點被重複執行,如果在執行的時候把執行過的子節點儲存起來,後面要用到的時候直接查表呼叫的話可以節約大量的時間。下面就看看動態規劃的兩種方法怎樣來解決斐波拉契數列fibonacci 數列問題。

二、自頂向下的備忘錄法

public static int fibonacci(int n)

public static int fib(int n,int memo)

建立了乙個n+1大小的陣列來儲存求出的斐波拉契數列中的每乙個值,在遞迴的時候如果發現前面的fib(n)的值計算出來就不再計算,如果未計算出來,則計算出來後儲存在memo陣列中,下次在嗲用fib(n)的時候就不會重複遞迴了。

比如上面的遞迴樹中fin(6)計算fib(5),呼叫fib(5)計算出了fib(4)後,fib(6)再嗲用fib(4)就不會遞迴fib(4)的子樹了,因為fib(4)的值已經儲存再memo[4]中

三、自底向上的動態規劃

備忘錄法還是利用了遞迴,上面演算法不管怎樣,計算fib(6)的時候最後還是要計算出fib(1),fib(2),fib(3)……,那麼何不先計算出fib(1),fib(2),fib(3)……,呢?這也就是動態規劃的核心,先計算子問題,再由子問題計算父問題。

public static int fib(int n)

return memo_i;

}

一般來說由於備忘錄方式的動態規劃方法使用了遞迴,遞迴的時候會產生額外的開銷,使用自底向上的動態規劃方法要比備忘錄方法好。

你以為看懂了上面就懂動態規劃了??那你就想的太簡單了,動態規劃問題遠遠不止,具體例項請看下次分析!

動態規劃法

在學習動態規劃法之前,我們先來了解動態規劃的幾個概念 1 階段 把問題分成幾個相互聯絡的有順序的幾個環節,這些環節即稱為階段。2 狀態 某一階段的出發位置稱為狀態。3 決策 從某階段的乙個狀態演變到下乙個階段某狀態的選擇。4 狀態轉移方程 前一階段的終點就是後一階段的起點,前一階段的決策選擇匯出了後...

動態規劃法

有些問題在分解時會產生許多子問題,且分解出的自問題互相交織,因而在解這類問題時,將可能重複多次解乙個子問題。這種重複當然是不必要的,解決方法可以在解決每個子問題後把它的解 包括其子子問題的解 保留在乙個 中,若遇到求與之相同的子問題時,dp演算法又稱動態規劃,是資訊學競賽中選手必須熟練掌握的一種演算...

動態規劃法

最近遇到了一道挺有意思的演算法題 四種硬幣 1元3元4元5元 問 想要湊成n元錢最少幾枚硬幣?public class coinsgamemain fun 7,is public static void fun int k,int is i1 l min i2 if l k private stat...