//暴力搜索
#include<iostream>
#include<cstring>
using namespace std;
const int N=305;
int n,m,h[N][N],ans;
bool flag[N][N];
int dx[4]={0,0,-1,1};
int dy[4]={1,-1,0,0};
void input(){
cin>>n>>m;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>h[i][j];
}
void dfs(int x,int y,int sum){
flag[x][y]=1;
for(int i=0;i<4;i++){
int xx=x+dx[i],yy=y+dy[i];
if(xx>=1&&xx<=n&&yy>=1&&yy<=m){
if(!flag[xx][yy]&&h[xx][yy]<h[x][y]){
flag[xx][yy]=1;
dfs(xx,yy,sum+1);
flag[xx][yy]=0;
}
}
}
if(sum>ans){
ans=sum;
}
return ;
}
int main(){
input();
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
memset(flag,0,sizeof flag);
dfs(i,j,1);
}
}
cout<<ans<<endl;
return 0;
}
//动态规划
#include<iostream>
#include<cstring>
using namespace std;
const int N=305;
int n,m,h[N][N],dx[4]={0,0,-1,1},dy[4]={1,-1,0,0},ans;
int dp[N][N];
//dp[i][j]:一条以(i,j)为终点的路径的长度
//性质:max
//状态计算:dp[x][y]=dp[xx][yy]+1
void input(){
cin>>n>>m;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>h[i][j];
}
//动态规划函数,用于计算以(x,y)为终点的最长路径长度
int DP(int x,int y){
//如果dp[x][y]已经被计算过,直接返回它的值,避免重复计算
if(dp[x][y]!=-1) return dp[x][y];
//初始化dp[x][y]为1,因为至少包含自身
dp[x][y]=1;
for(int i=0;i<4;i++){
int xx=x+dx[i],yy=y+dy[i];
if(xx>=1&&xx<=n&&yy>=1&&yy<=m){
if(h[xx][yy]<h[x][y]){
dp[x][y]=max(dp[x][y],DP(xx,yy)+1);
}
}
}
return dp[x][y];
}
int main(){
input();
memset(dp,-1,sizeof dp);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
ans=max(ans,DP(i,j));
}
}
cout<<ans<<endl;
return 0;
}