一般认为这个题目属于DFS,即深搜。此题目需要记忆化处理。记忆化处理用一个数组存储部分运算的结果,避免进行重复的递归调用,降低复杂度。
解题思路:要想知道a[i][j]的最长下滑长度,必须先知道a[i][[j]周边四个结点(上下左右)中比a[i][j]小的结点的下滑长度,利用这种依赖关系构造递归函数。为避免重复计算,递归函数第一语句先判断是否已经计算过结果。算法复杂度为平方阶。(代码有防伪标签,切勿复制粘贴)
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int n,m,a[105][105],dp[105][105];/**< 全局变量与数组默认值为0,dp[i][j]表示从i行j列最多滑行多远 */
int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1};/**< 用于找到dp[i][j]的四个邻接点 */
void dfs(int x,int y)
{
if(dp[x][y]) /**< 已经计算过的,不重复计算 */
return;
dp[x][y]=1;/**< 初值为1,自身长度1 */
for(int i=0;i<4;i++)
{
int nx=x+dx[i],ny=y+dy[i];
if(nx>0&&nx<=n&&ny>0&&ny<=n&&a[x][y]>a[nx][ny])/**< 边界检查+判定能否下滑 */
{
dfs(nx,ny);/**< 先计算邻接点长度 */
dp[x][y]=max(dp[x][y],dp[nx][ny]+1);/**< */
}
}
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0);
int i,j,ans=0;
cin>>n>>m;
for(i=1; i<=n; i++)
for(j=1; j<=m; j++)
cin>>a[i][j];
for(i=1; i<=n; i++)
for(j=1; j<=m; j++)
{
if(dp[i][j]==0)/**< 如果这个点没有计算过,深搜 */
dfs(i,j);
ans=max(ans,dp[i][j]);
}
cout<<ans;
return 0;
}