記憶化搜尋實際上是遞迴來實現的,但是遞迴的過程中有許多的結果是被反覆計算的,這樣會大大降低演算法的執行效率。
而記憶化搜尋是在遞迴的過程中,將已經計算出來的結果儲存起來,當之後的計算用到的時候直接取出結果,避免重複運算,因此極大的提高了演算法的效率。
對於乙個遞迴函式w(a,b,c)
這是個簡單的遞迴函式,但實現起來可能會有些問題。當a,b,c均為15時,呼叫的次數將非常的多。你要想個辦法才行.
/* absi2011 : 比如 w(30,-1,0)既滿足條件1又滿足條件2
這種時候我們就按最上面的條件來算
所以答案為1
*/輸入格式:
會有若干行。
並以-1,-1,-1結束。
保證輸入的數在[-9223372036854775808,9223372036854775807]之間,並且是整數。
輸出格式:
輸出若干行,每一行格式:
w(a, b, c) = ans
注意空格。
輸入樣例#1: 複製
1 1 1輸出樣例#1: 複製2 2 2
-1 -1 -1
w(1, 1, 1) = 2w(2, 2, 2) = 4
這是乙個非常經典的記憶化搜尋的題目。拿到這個題,首先可以想到的就是遞迴的方法,看上去用遞迴可以輕而易舉的解決。但是遞迴的開銷是不一般的大。下面先給大家上乙個遞迴的**,以便和之後的記憶化搜尋的進行對比。
1 #include2 #include3 #include //執行結果用來記時
4using
namespace
std;
5clock_t start, finish;
6double
duration;
78 typedef long
long
ll;9 ll f[30][30][30
];10
11int w(ll a, ll b, ll c)
15else
if(a>20||b>20||c>20)18
else
if(ac)
21else24}
2526
intmain()38}
39return0;
40 }
開闢乙個陣列 f,用來儲存計算出來的結果。
關於陣列的大小:因為題目中給出了乙個條件 「 如果 a>20 or b>20 or c>20就返回w(20,20,20) 」 那麼陣列只要最小開到 f[21][21][21]就夠用了。
具體的步驟看**中的註解。
1 #include2 #include3 #include 4執行結果using
namespace
std;
5clock_t start, finish;
6double
duration;
78 typedef long
long
ll;9 ll f[30][30][30
];10
11int
w(ll a, ll b, ll c)
15else
if(a>20||b>20||c>20)18
else
if(f[a][b][c]!=0)return f[a][b][c]; //
如果之前被計算過,那麼直接返回存在陣列中的結果
19//
沒有計算過的,就進行的計算
20else
if(ac)
23else
26return f[a][b][c]; //
計算完畢之後返回計算出的結果 27}
2829
intmain() 41}
42return0;
43 }
大家和遞迴的執行時間對比一下就可以看出,當遞迴的次數多了之後,效率要高出很多。
根據上面的題,可以總結乙個記憶化搜尋的過程。
1f(problem p)else
暴力搜尋演算法,記憶搜尋演算法,動態規劃演算法
以下這道題通過一步一步的分析優化可以看出暴力搜尋方法,記憶搜尋方法,動態規劃方法的優化過程,往往寫出暴力搜尋方法是比較容易的,這樣一步步的分析可以更好的理解動態規劃方法。題目 給定陣列arr,arr中所有的值都為正數且不重複。每個值代表一種面值的貨幣,每種面值的貨幣可以使用任意張,再給定乙個整數ai...
A 搜尋演算法
啟發式搜尋演算法 要理解 a 搜尋演算法,還得從啟發式搜尋演算法開始談起。所謂啟發式搜尋,就在於當前搜尋結點往下選擇下一步結點時,可以通過乙個啟發函式 來進行選擇,選擇代價最少的結點作為下一步搜尋結點而跳轉其上 遇到有乙個以上代價最 少的結點,不妨選距離當前搜尋點最近一次展開的搜尋點進行下一步搜尋 ...
A 搜尋演算法
a 演算法是基於bfs的一種入門級啟發式搜尋演算法,就是將bfs的佇列改為基於估價的優先佇列,可以快速地找到答案。優先隊列為小根堆 while 優先佇列不為空 取出隊頭並擴充套件 將擴充套件節點以估價值 當前值為優先順序入隊 endwhile估價函式越接近真實值演算法越優,但一定不能大於真實值,否則...