0.前言
有些時候樸素深蒐會出現超時情況,所以誕生出一種記憶化搜尋的dfs,其實它也是dfs,只不過在dfs的過程中,新增了賦值的過程,這個賦值的過程就叫做記憶。這裡面會根據一些題目來講解記憶化搜尋。
1.樣例分析
1.1 題目 絡谷 p1434滑雪
1.2分析
1.3**
#include
using
namespace std;
const
int maxn =
105;
int n,m;
//行列
int arr[maxn]
[maxn]
;//初始的二維序列
int dis[maxn]
[maxn]
;// dis[i][j]表示(i,j)能夠滑行的最遠距離
intgetmax
(int a,
int b,
int c,
int d)
//計算(x,y)能夠滑行的最遠距離sum
//prior表示上乙個數是多少
intdfs
(int x,
int y,
int prior)
if(dis[x]
[y]!=0)
prior = arr[x]
[y];
dis[x]
[y]=
getmax
(//3.返回四個中的最大值,並賦值給dis[x][y]
dfs(x-
1,y,prior)
,dfs
(x,y+
1,prior)
,dfs
(x+1
,y,prior)
,dfs
(x,y-
1,prior))+
1;//4.返回最後的計算結果(為main函式中的tempdis服務)
return dis[x]
[y];
}int
main()
}for
(int i =
0;i}
cout << maxdis<<
"\n"
;}
1.4 測試用例:3 3
1 1 3
2 3 4
1 1 1
4
2.反例分析
是不是什麼情況都適合使用記憶化搜尋呢?肯定不是!
今天在寫到絡谷的一道題【
[usaco08jan]牛大賽cow contest 】時,想著是不是可以使用記憶化搜尋。舉例如下。
輸入樣例:奶牛4打敗了2,2又打敗了1,5打敗了2。
這樣我們就可以記錄win[1]=0,win[2]=1,win[4]=2
。等第搜尋5時,發現2已經搜尋過了,直接返回win[2]+1 = 2
,這樣就算出來了win[5]=2
。但是這樣真的合適嗎?就拿題中給出的測試用例:
5 5
4 34 2
3 21 2
2 5
這時記憶化搜尋就行不通了,原因是會 出現重複計算。
假設先計算奶牛2,發現奶牛2勝過的牛有1頭(即win[2]=1
)。
計算3時,2已經計算過了,直接返回win[2]+1 = 2
;計算4時,因為4即可到2,又可到3,且他們都已經訪問過了,所以有win[4] += (win[2]+1) = 3;
,win[4] += (win[3]+1) =5;
就產生了重複計算的問題。
記憶化搜尋
演算法上依然是搜尋的流程,但是搜尋到的一些解用 動態規劃 的那種思想和模式作一些儲存。一般說來,動態規劃總要遍歷所有的狀態,而搜尋可以排除一些無效狀態。更重要的是搜尋還可以剪枝,可能剪去大量不必要的狀態,因此在空間開銷上往往比動態規劃要低很多。記憶化演算法在求解的時候還是按著自頂向下的順序,但是每求...
記憶化搜尋
記憶化搜尋 演算法上依然是搜尋的流程,但是搜尋到的一些解用動態規劃的那種思想和模式作一些儲存。記憶化演算法在求解的時候還是按著自頂向下的順序,但是每求解乙個狀態,就將它的解儲存下來,以後再次遇到這個狀態的時候,就不必重新求解了。例1.題目描述 給從左至右排好隊的小朋友們分糖果,要求 1.每個小朋友都...
記憶化搜尋
原文 感謝作者。一.動態規劃 動態規劃 dynamic programming 與 分治思想 有些相似,都是利用將問題分 為子問題,並通過合併子問題的解來獲得整個問題的解。於 分治 的不同之處在 於,對於乙個相同的子問題動態規劃演算法不會計算第二次,其實現原理是將每乙個計算過的子問題的值儲存在乙個表...