浅刷记忆化搜索(P1434 [SHOI2002] 滑雪)

dfs过程中拿一个数组记录每一步的答案,这样就不需要重复计算其中的某一步,减小计算量

简单来说就是对dfs的优化

如题:

P1434 [SHOI2002] 滑雪

普通思路就是写dfs把每个点搜一遍,找到下一个比原来点小的点,但是这样写会超时,应该其中的点可能不止计算过一次,举个栗子

1 2 3 

4 5 6 

7 8 9

从“9”到“1”,可以从“9”-“6”-“3”-“2”-“1”,这样就会判断递归4次,然后还得从1逐层进行dfs,如果数据量较大,就很容易超时,所以只需要将每一个点到最低点的距离储存起来,这样每个点只需要处理为比自己小的点+1,比如从“9”到“1”就只需要“9”-“8”+1或者“9”-“6”+1(好规),先将数组赋值为其中一个,再跟另外一个进行比较,较大的就是ans。

我拿vis数组作为储存某一个点的数组,每次遇到新的点,先赋值为1进行标记,然后再dfs搜索比他小的点,直到搜到最小的点,赋值为1,然后依次往上+1,如果遇到的是储存过数值的点,那么就直接返回这个点的值,避免重复计算

具体看代码

#include<bits/stdc++.h>//懂得都懂
using namespace std;//没什么好说的
int r,c,ans=0;//r是列数(对应x),c是行数(对应y),切记不能搞反
int a[600][600];//储存每个点的高度
int vis[600][600];//储存每个点到最低点的距离,也就是答案
int dx[4]={0,0,1,-1};//x的四个方向
int dy[4]={1,-1,0,0};//y的四个方向
int dfs(int x,int y)//简简单单的dfs
{
	if(vis[x][y]!=0)//避免重复计算
	{
		return vis[x][y];
	}
	s[x][y]=1;//先标记为1,如果有比它还小的点,再进行赋值
	for(int i=0;i<4;i++)//四个方向
	{
		int xx=x+dx[i];
		int yy=y+dy[i];
		if(xx>0&&xx<=r&&yy>0&&yy<=c&&a[x][y]>a[xx][yy])//判断是否出界和寻找比(x,y)小的(xx,yy)
		{
			dfs(xx,yy);//将这一点以下的所有符合上述条件的点标记为1或者赋值为上一个点(比它小的点)+1
			vis[x][y]=max(vis[x][y],vis[xx][yy]+1);赋值
		}
	}
	return vis[x][y];	返回该点到最低点的距离
}
int main()
{
	cin>>r>>c;输入
	for(int i=1;i<=r;i++)
	{
		for(int j=1;j<=c;j++)
		{
			cin>>a[i][j];还是输入
		}
	}
	for(int i=1;i<=r;i++)
	{
		for(int j=1;j<=c;j++)
		{
			ans=max(ans,dfs(i,j));处理,判断(i,j)点所储存的距离和ans的大小,用ans储存答案,使得答案永远是较大的那一个
		}
	}	
	cout<<ans;输出结束
    return 0;
} 

 

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值