简单理解记忆化搜索

简单的原理描述
一般来说,我们写 d f s dfs dfs返回值都是 v o i d void void,但是如果想要记忆化搜索,那么 d f s dfs dfs的返回值就不能是 v o i d void void,因为我们利用每一次搜索的结果进而达到记忆化:之前搜过的就不用再搜了。
具体题目:滑雪(题目描述见链接)
解题思路
①如何进行 d f s dfs dfs
因为可以向四个方向前进,所以我们用两个数组来确定方向

int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};

而且还要保证前面的高度大于后面,这个作为是否进行 d f s dfs dfs的条件之一。
②如何进行记忆化
举个例子
1 1 3 4 5 6 7 8 9 (1) \begin{matrix} 1 & 1 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{matrix} \tag{1} 147158369(1)
对于 ( 1 , 1 ) (1,1) (1,1)很明显,最大距离为1。
对于 ( 1 , 2 ) (1,2) (1,2)很明显,最大距离为1。
对于 ( 1 , 3 ) (1,3) (1,3)最大距离为2, ( 1 , 3 ) → ( 1 , 2 ) 。 (1,3){\rightarrow}(1,2)。 (1,3)(1,2)
对于 ( 2 , 1 ) (2,1) (2,1)最大距离为2, ( 2 , 1 ) → ( 1 , 1 ) 。 (2,1){\rightarrow}(1,1)。 (2,1)(1,1)
对于 ( 2 , 2 ) (2,2) (2,2)最大距离为3,如果不用记忆化,搜索的过程为 ( 2 , 2 ) → ( 2 , 1 ) → ( 1 , 1 ) (2,2){\rightarrow}(2,1){\rightarrow}(1,1) (2,2)(2,1)(1,1),但是如果我们把 ( 2 , 1 ) (2,1) (2,1)的最大距离记下来,那么搜索的仅过程为 ( 2 , 2 ) → ( 2 , 1 ) (2,2){\rightarrow}(2,1) (2,2)(2,1),然后让当前的距离加以已经搜索过的位置的最大距离
实现的难题在于,对于每一颗搜索的子树,都要记录最大距离,比如我在第一层开始搜索,搜到第二层时,我也要在这一次搜索时,把第二层的最大距离记下来。

#include<iostream>
#include<cmath>		//调用max函数
using namespace std;
int R,C,total;		//total用来记录最大距离
int ice[105][105];	//记录高度
int step[105][105];	//记录是否搜索过和最大距离
int X[4]={1,0,-1,0};	//记录两个方向
int Y[4]={0,1,0,-1};
int dfs(int,int);
int main()
{
	cin>>R>>C;
	int t,j;
	for(t=0;t<R;t++)
	{
		for(j=0;j<C;j++)
		{
			cin>>ice[t][j];
		}
	}
	
	for(t=0;t<R;t++)
	{
		for(j=0;j<C;j++)
		{
			total=max(total,dfs(t,j));
		}
	}	
	cout<<total;
}

int dfs(int row,int column)
{
	if(step[row][column])		//如果已经搜索过就直接返回
		return step[row][column];
	step[row][column]=1;	//搜到这一层时,先记录它为1
	
	int t,x,y;
	for(t=0;t<4;t++)
	{
		x=row+X[t];
		y=column+Y[t];
		if(x>=0&&x<R&&y>=0&&y<C&&ice[x][y]<ice[row][column])
		{
			dfs(x,y);
			//找到可能的4个方向中最大距离	step[x][y]+1为下一层的最大距离
			step[row][column]=max(step[row][column],step[x][y]+1)
		}
	}
	
	return step[row][column];
}

这道题中,很关键的步骤是,搜到这个节点时,就先让它的值为1,然后在这个节点继续搜。当搜到那些距离只为1时,就返回1,然后往上面的结点传递这个值,记忆化搜索的关键是找一个数组把各个结点的值存下来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值