記錄結果再利用的「動態規劃」

2021-10-11 02:58:54 字數 1397 閱讀 5405

書中以揹包為例子,和樹狀dp 不同,是種一維dp.

如果不記憶化,複雜度為o(n^2)

只不過,這種方法的搜尋深度是n,而且每一層的搜尋都需要兩次分支,最壞就需要o(2」)的時間,

當n比較大時就沒辦法解了。所以要怎麼辦才好呢?為了優化之前的演算法,我們看一下針對樣例

輸入的情形下rec遞迴呼叫的情況。

如圖所示,rec以(3,2)為引數呼叫了兩次。如果引數相同,返回的結果也應該相同,於是第二次調

用時已經知道了結果卻白白浪費了計算時間。讓我們在這裡把第一次計算時的結果記錄下來,省

略掉第二次以後的重複計算試試看。

記憶化搜尋後就僅需o(nw)的複雜度(注*:n是物品個數,w是揹包狀態)

講解了記憶化搜尋的***(見圖一)和不利於記憶化搜尋的***(見碼二)

碼一:

int dp[max_n +1]

[max_w +1]

;//記憶化陣列

intrec

(int i,

int j)

//將結果記錄在陣列中

return dp[i]

[j]= res;

void

solve()

碼二:

窮竭搜尋的寫法

如果對記憶化搜尋還不是很熟練的話,可能會把前面的搜尋寫成下面這樣

// 目前選擇的物品價值總和是sum,從第1個物品之後的物品中挑選重量總和小於j的物品

intrec

(int i,

int j,

int sum)

{int res;

if(i ==n)

{//已經沒有剩餘物品了

res = sum;

} else

if(j//無法挑選這個物品

res =

rec(i +

1, j, sum)

;} else

{//挑選和不挑選的兩種情況都嘗試一下

res =

max(

rec(i +

1, j, sum)

,rec

(i +

1, j - w[i]

, sum +v[i]))

;return res;

在需要剪枝的情況下,可能會像這樣把各種引數都寫在函式上,但是在這種情況下會讓記憶

化搜尋難以實現,需要注意。

兩者的區別就是前者是返回截止每層的最大值(每層皆返回)

數都寫在函式上,但是在這種情況下會讓記憶

化搜尋難以實現,需要注意。

兩者的區別就是前者是返回截止每層的最大值(每層皆返回)

後者是到最後才返回,這樣的動態規劃不利於每層都記錄。

動態規劃學習記錄

動態規劃一般用陣列記錄下每一步的最優值,返回最後一步的值就是最優結果,相對於遞迴解法消除了重複計算的部分,提高的效率。計數 有多少種方式從a到b 多少種方式取得某值 求最優解 最大值最小值 路徑上最大資料和。存在性問題 能不能選出和為k的數 選定演算法前一定要判斷是否為動態規劃解題 有時候問題相似但...

經典動態規劃學習記錄

動態規劃本質是一種用空間換時間的優化方法,通常來優化可以暴力搜尋求解的問題,也就是去冗餘,把之前計算過的存下來,而且是規定了遞迴的計算順序,從簡單基本的出發,依次計算 這也是他優於記憶搜尋的地方 方法大概如下 1.首先能明白暴力遞迴怎麼實現 重要 2.找到函式中可以代表遞迴過程的引數 3.引數為ke...

利用動態規劃方法求素數

因為任何乙個正整數都可以通過素數相乘得到,由此我們可以知道 素數可以視為不能被小於它 或它的平方根 的素數整除的數。通過動態規劃的思想,很容易聯想到,如果將求得的素數儲存起來,那麼在計算後面的素數時,只需要遍歷求模已求得的素數表,而避免進行過多的無效操作。以下為 include include in...