有些时候朴素深搜会出现超时状况,因此诞生出一种记忆化搜索的dfs,其实它也是dfs,只不过在dfs的过程当中,添加了赋值的过程,这个赋值的过程就叫作记忆。这里面会根据一些题目来说解记忆化搜索。ios
#include<iostream> using namespace std; const int maxN = 105; int n,m;//行列 int arr[maxN][maxN];//初始的二维序列 int dis[maxN][maxN];// dis[i][j]表示(i,j)可以滑行的最远距离 int getMax(int a,int b,int c,int d){//从4个整数中取最大值 return max((max(a,b)),max(c,d) ); } //计算(x,y)可以滑行的最远距离sum //prior表示上一个数是多少 int dfs(int x,int y,int prior){ //1.若是越界 或者 高度达不到要求 if(x<0 || x>=n || y<0 || y>=m || prior <= arr[x][y] ){ return 0; } if(dis[x][y] != 0){//2.若是已经计算过,就不用再计算了,直接返回便可 return dis[x][y]; } 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(){ cin >> n>> m; fill(dis[0],dis[0]+maxN*maxN,0);//初始化为0 int maxDis = 0; for(int i = 0;i<n;i++){ for(int j = 0;j<m;j++){ cin >> arr[i][j]; } } for(int i = 0;i<n;i++){ for(int j = 0;j<m;j++){ //(i,j) int tempDis = dfs(i,j,9999);//深搜 if(maxDis < tempDis ){ maxDis = tempDis;//深搜 } } } cout << maxDis<<"\n"; }
3 3 1 1 3 2 3 4 1 1 1 4
是否是什么状况都适合使用记忆化搜索呢?确定不是!
今天在写到络谷的一道题【
[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。可是这样真的合适吗?就拿题中给出的测试用例:ide
5 5 4 3 4 2 3 2 1 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;就产生了重复计算的问题。函数