//爆搜 9/12
//不用st标记是否遍历过,因为遍历的路线呈下降趋势(拓扑序),不可回到前面的点
#include <iostream>
using namespace std;
const int N = 310;
typedef pair<int,int>PII;
#define x first
#define y second
int n,m;
int g[N][N];
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
int dfs(int x,int y)
{
int res=0;
for(int i=0;i<4;i++)
{
int a=x+dx[i],b=y+dy[i];
if(a<1||a>n||b<1||b>m) continue;
if(g[a][b]>=g[x][y]) continue;
res=max(res,dfs(a,b));
}
return res+1;
}
int main()
{
int ans=0;
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>g[i][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
ans=max(ans,dfs(i,j));
cout<<ans;
return 0;
}
//记忆化搜索
//因为成拓扑序,有依赖关系,把每个点可以到达的最长距离记录下来,减少冗余计算,f[i][j]:从(i,j)出发可以到达的最长距离
#include <iostream>
#include <cstring>
using namespace std;
const int N = 310;
int n,m;
int g[N][N];
int f[N][N];
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
int dp(int x,int y)
{
int &v=f[x][y];
if(v!=-1) return v;
v=1;
for(int i=0;i<4;i++)
{
int a=x+dx[i],b=y+dy[i];
if(a<1||a>n||b<1||b>m) continue;
if(g[a][b]>=g[x][y]) continue;
v=max(v,dp(a,b)+1);
}
return v;
}
int main()
{
memset(f,-1,sizeof f);
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>g[i][j];
int ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
ans=max(ans,dp(i,j));
cout<<ans;
return 0;
}