最優子結構與記憶化搜尋

2021-08-25 11:58:42 字數 960 閱讀 8045

源於對演算法競賽一書的理解

最優子結構:先來看乙個數塔

從最頂部的結點出發,每次可以向左或者向右走一格,走到最底部時把沿途經歷的結點全部加起來,如何走才能和最大。

可以用乙個二維陣列a(i,j)記錄這張數塔圖,每乙個結點的位置(i,j),都可以看作是乙個狀態,則從當前狀態出發,下乙個狀態可以是(i+1,j)或者是(i+1,j+1),而題目就是求從狀態(0,0)出發,不斷的狀態進行轉移,轉移到最底部時所得的和最大值。設d(0,0)為從狀態(0,0)出發得到的和最大值,則d(0,0)=a(0,0)+d(1,0)或者d(0,0)=a(0,0)+d(1,1);要得到最大值只能是其中一種走法,所以d(0,0)=a(0,0)+max(d(1,0),d(1,1)),即當前最優解等於下一子狀態的最優解加上當前結點值。當下一子狀態都不是最優解時,當前狀態一定不是最優解。這就是最優子結構。

遞迴演算法如下:

int solve(int i,int j)

但是這樣做這道題,相當於從節點開始往下搜尋,由於總共層數有n層,一共有2的n次-1個結點要被執行,所以 時間複雜度為o(2^n),過於複雜,這是因為有很多結點被重複執行了,比如從狀態(2,1)要轉移到(3,2),而從狀態(2,2)也要轉移到(3,2),這樣從(3,2)這個結點往下的子樹就被執行了兩次,更何況,別的結點及以下的子樹也會發生這種情況,時間複雜度就這樣上來了。因此採用記憶化搜尋來保證每個結點及以下的子樹只走一次。

記憶化搜尋:

如果把每從乙個狀態出發後所得的最優解記錄在乙個陣列dp[i][j]中,那麼當下一次又執行到這個狀態時,就可以返回了,避免了重複操作。

**int solve(int i,int j)

這裡賦值語句本身有返回值。即把值賦給dp[i][j]後,又可以把dp[i][j]的值返回。

wenbao與記憶化搜尋

記憶化搜尋 通俗地講就是搜尋的形式,dp的思想 一些搜尋難以完成,dp的動態轉移方程又不好寫的題,就會用到記憶化搜尋,利用dp記錄路徑 相當於為dfs剪枝 用dfs進行模擬。啦啦啦啦啦啦,好厲害!弱雞 1 include 2 include 3 include 4 using namespace s...

1106 最優對稱路徑(最短路 記憶化搜尋)

submit page summary time limit 1 sec memory limit 128 mb submitted 486 solved 135 給乙個n行n列的網格,每個格仔裡有乙個1到9的數字。你需要從左上角走到右下角,其中每一步只能往上 下 左 右四個方向之一走到相鄰格仔,不...

記憶化搜尋

演算法上依然是搜尋的流程,但是搜尋到的一些解用 動態規劃 的那種思想和模式作一些儲存。一般說來,動態規劃總要遍歷所有的狀態,而搜尋可以排除一些無效狀態。更重要的是搜尋還可以剪枝,可能剪去大量不必要的狀態,因此在空間開銷上往往比動態規劃要低很多。記憶化演算法在求解的時候還是按著自頂向下的順序,但是每求...