问题描述:

小蓝准备在一个空旷的场地里面滑行,这个场地的高度不一,小蓝用一个 n 行 m 列的矩阵来表示场地,矩阵中的数值表示场地的高度。
如果小蓝在某个位置,而他上、下、左、右中有一个位置的高度(严格)低于当前的高度,小蓝就可以滑过去,滑动距离为 1 。
如果小蓝在某个位置,而他上、下、左、右中所有位置的高度都大于等于当前的高度,小蓝的滑行就结束了。

  小蓝不能滑出矩阵所表示的场地。

  小蓝可以任意选择一个位置开始滑行,请问小蓝最多能滑行多远距离。

输入第一行包含两个整数 n, m,用一个空格分隔。

接下来 n 行,每行包含 m 个整数,相邻整数之间用一个空格分隔,依次表示每个位置的高度。

输出一行包含一个整数,表示答案。

对于 30% 评测用例,1 <= n <= 20,1 <= m <= 20,0 <= 高度 <= 100。 对于所有评测用例,1 <= n <= 100,1 <= m <= 100,0 <= 高度 <= 10000。

样例输入
4 5
1 4 6 3 1 
11 8 7 3 1 
9 4 5 2 1 
1 3 2 2 1
样例输出
7
样例说明

滑行的位置以此为
(2,1),(2,2),(2,3),(3,3),(3,2),(4,2),(4,3)。

  • 每个位置都要经历以下的步骤寻找出路 alt

  • 代码实现 (此代码在考试时敲得,可能会出现一些错误,如有错误,请多多指正)

// 爆搜(会超时只能过30%的样例)
#include <bits/stdc++.h>
using namespace std;
const int N=1e3+10;
int a[N][N],b[N][N];
int dx[]={1,0,-1,0},dy[]={0,1,0,-1};//偏移量技巧
int n,m;
int dfs(int x,int y)
{
	int cnt=0;// 初始值为0
	for(int i=0;i<4;i++)
	{
		int nx=x+dx[i],ny=y+dy[i];
		if(nx>=0&&nx<n&&ny>=0&&ny<m&&!b[nx][ny]&&a[nx][ny]<a[x][y])// 判断是否在边界以内,是否是第一次遍历,是否满足题中所给的滑倒下一个区域的条件
		{
			b[nx][ny]=1;// 表示该位置已经走过一次
			cnt=max(cnt,dfs(nx,ny));
			b[nx][ny]=0;// 回溯 恢复现场
		}
	}
	return cnt+1;// 算上自身 cnt加1
}
int main ()
{
	cin>>n>>m;
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++){
			scanf("%d",&a[i][j]);// 打蓝桥杯的时候,输入输出尽量用scanf和printf,不然容易卡时间 
		}
	}
	int res=0;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
        	b[i][j]=1;// 表示被遍历过一次
			res=max(res,dfs(i,j));
            b[i][j]=0;// 恢复现场
		}
	} 
	printf("%d\n",res);
	return 0;
}
// 记忆化搜索(用另一个数组记录该点经过DFS后得到的最大滑行距离)
#include <bits/stdc++.h>
using namespace std;
const int N=1e3+10;
int a[N][N],d[N][N];// 记忆化搜索中d[N][N]不仅代表该点是否遍历过,且表示该点DFS后的最远距离 
int dx[]={1,0,-1,0},dy[]={0,1,0,-1};
int n,m;
int dfs(int x,int y)
{
	int cnt=0;
	if(d[x][y]!=-1) return d[x][y];//如果该点在记忆化数组中 直接返回
	for(int i=0;i<4;i++)
	{
		int nx=x+dx[i],ny=y+dy[i];
		if(nx>=0&&nx<n&&ny>=0&&ny<m&&a[nx][ny]<a[x][y])
		{
			cnt=max(cnt,dfs(nx,ny));//寻找该点所能遍历的长度的最大值
		}
	}
	d[x][y]=cnt+1; //记录该点
	return d[x][y];
}
int main ()
{
	cin>>n>>m;
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++){
			scanf("%d",&a[i][j]);// 打蓝桥杯的时候,输入输出尽量用scanf和printf,不然容易卡时间 
		}
	}
	memset(d,-1,sizeof d);
	int res=0;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{ 
			res=max(res,dfs(i,j));
		}
	} 
	printf("%d\n",res);
	return 0;
}