数据结构-记忆化搜索讲解
算法:記憶化搜索算法
一:簡(jiǎn)述
記憶化搜索實(shí)際上是遞歸來(lái)實(shí)現(xiàn)的,但是遞歸的過程中有許多的結(jié)果是被反復(fù)計(jì)算的,這樣會(huì)大大降低算法的執(zhí)行效率。
而記憶化搜索是在遞歸的過程中,將已經(jīng)計(jì)算出來(lái)的結(jié)果保存起來(lái),當(dāng)之后的計(jì)算用到的時(shí)候直接取出結(jié)果,避免重復(fù)運(yùn)算,因此極大的提高了算法的效率。
二:應(yīng)用實(shí)例
題目描述
對(duì)于一個(gè)遞歸函數(shù)w(a,b,c)
如果 a<=0 or b<=0 or c<=0 就返回值1.
如果 a>20 or b>20 or c>20就返回w(20,20,20)
如果 a<b并且b<c 就返回w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c)
其它的情況就返回w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1)
這是個(gè)簡(jiǎn)單的遞歸函數(shù),但實(shí)現(xiàn)起來(lái)可能會(huì)有些問題。當(dāng)a,b,c均為15時(shí),調(diào)用的次數(shù)將非常的多。你要想個(gè)辦法才行.
/* absi2011 : 比如 w(30,-1,0)既滿足條件1又滿足條件2
這種時(shí)候我們就按最上面的條件來(lái)算
所以答案為1
*/
輸入輸出格式
輸入格式:
會(huì)有若干行。
并以-1,-1,-1結(jié)束。
保證輸入的數(shù)在[-9223372036854775808,9223372036854775807]之間,并且是整數(shù)。
輸出格式:
輸出若干行,每一行格式:
w(a, b, c) = ans注意空格。
輸入輸出樣例
輸入樣例#1:
1 1 1
2 2 2
-1 -1 -1
輸出樣例#1:
w(1, 1, 1) = 2
w(2, 2, 2) = 4
這是一個(gè)非常經(jīng)典的記憶化搜索的題目。
拿到這個(gè)題,首先可以想到的就是遞歸的方法,看上去用遞歸可以輕而易舉的解決。但是遞歸的開銷是不一般的大。下面先給大家
運(yùn)行結(jié)果:
記憶化搜索解法
開辟一個(gè)數(shù)組 f[][][],用來(lái)存儲(chǔ)計(jì)算出來(lái)的結(jié)果。
關(guān)于數(shù)組的大小:因?yàn)轭}目中給出了一個(gè)條件 “ 如果 a>20 or b>20 or c>20就返回w(20,20,20) ” 那么數(shù)組只要最小開到 f[21][21][21]就夠用了。
具體的步驟看代碼中的注解。
#include<iostream> #include<cstdio> #include <time.h> using namespace std; clock_t start, finish; double duration;typedef long long ll; ll f[30][30][30];int w(ll a, ll b, ll c){if(a<=0||b<=0||c<=0){return 1;}else if(a>20||b>20||c>20){return w(20,20,20);}else if(f[a][b][c]!=0)return f[a][b][c]; //如果之前被計(jì)算過,那么直接返回存在數(shù)組中的結(jié)果 //沒有計(jì)算過的,就進(jìn)行的計(jì)算 else if(a<b&&b<c){ f[a][b][c] = w(a,b,c-1) + w(a,b-1,c-1) - w(a,b-1,c);}else{f[a][b][c]=w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1);}return f[a][b][c]; //計(jì)算完畢之后返回計(jì)算出的結(jié)果 }int main(){ll a, b, c;while(1){cin >> a >> b >> c;start = clock(); //開始計(jì)時(shí) if(a==-1&&b==-1&&c==-1) return 0;else{printf("w(%lld, %lld, %lld) = %d\n", a, b, c, w(a, b, c));finish = clock(); //結(jié)束記時(shí) duration = (double)(finish - start) / CLOCKS_PER_SEC; //計(jì)算持續(xù)時(shí)間 printf( "%f seconds\n", duration );} }return 0; }運(yùn)行結(jié)果
大家和遞歸的運(yùn)行時(shí)間對(duì)比一下就可以看出,當(dāng)遞歸的次數(shù)多了之后,效率要高出很多。
大家和遞歸的運(yùn)行時(shí)間對(duì)比一下就可以看出,當(dāng)遞歸的次數(shù)多了之后,效率要高出很多。
三:總結(jié)過程
根據(jù)上面的題,可以總結(jié)一個(gè)記憶化搜索的過程。
f(problem p){if(p has been solved){return the result }else{divide the p into some sub-problems (p1, p2, p3...)f(p1);f(p2);f(p3);...}總結(jié)
以上是生活随笔為你收集整理的数据结构-记忆化搜索讲解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java 洛谷 P1426 小鱼会有危险
- 下一篇: Java 洛谷 P1464 Functi