https://www.luogu.org/problemnew/show/P1434
用f[i][j]表示从(i,j)开始滑动到底部的最长距离, 很容易得到递推方程
f[i][j] = max(f[i1][j1], f[i2][j2],f[i3][j3],f[i4][j4])+1
即表示从(i,j)的上下左右的点出发的滑动的距离+1;
思路:
搜索从每个点开始能够滑动的最长的距离, 从每个点搜索的结果得储存,加快搜索速度(记忆化搜索)。
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstdio>
using namespace std;
int row, col, a[101][101];//行数,列数,滑道数据
int mark[101][101];//标记从(x0, y0)出发是否找到了最长滑道
int dx[]={-1, 0, 1, 0};//上右下左四个方向
int dy[] = {0, 1, 0, -1};//同上
int f[101][101];//f[i][j]储存从a[i][j]这个滑道开始滑最长的距离
int dfs(int x, int y)//从x,y开始滑动
{
bool tag =false;//标记是不是滑到底部了
for(int i = 0; i < 4; i++)//四个方向搜索
{
int x0 = x + dx[i];
int y0 = y + dy[i];
if(x0>=1 && x0<=row && y0>=1 && y0<=col && a[x0][y0] > a[x][y])
{
//如果在边界内并且可以往(x0, y0)这个方向滑动
tag = true;//标记滑动,没有滑到底
if(!mark[x0][y0])//如果从(x0,y0)出发滑动最长的距离还没有求
{
f[x0][y0] = dfs(x0, y0);//储存,即记忆化
mark[x0][y0] = 1;//标记从(x0,y0)出发滑动最长的距离已经求了
if(f[x0][y0] +1 > f[x][y])//更新滑动最长的距离
f[x][y] = f[x0][y0] +1;
mark[x][y] = 1;//标记从(x,y)出发滑动最长的距离已经求了
}
else
{
if(f[x0][y0] +1 > f[x][y])//更新
f[x][y] = f[x0][y0] +1;
mark[x][y] = 1;//标记从(x,y)出发滑动最长的距离已经求了
}
}
}
if(!tag)//底部只能滑一步
{
return 1;
}
else
return f[x][y];
}
int main()
{
cin>>row>>col;
for(int i = 1; i <= row; i++)
for(int j = 1; j <= col; j++)
cin>>a[i][j];
int t = 0;
for(int i = 1; i <= row; i++)
{
for(int j = 1; j <= col; j++)
{
int xx = dfs(i, j);//从(i, j)开始滑动
if(xx > t)
t = xx;
}
}
cout<<t<<endl;
//system("pause");
}