#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
struct node{
int x, y, sum;
node(int i, int j){
x = i; y = j; sum = 0;
}
map<pii, bool> mp;
};
int main(){
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n, m; cin>>n>>m;
int d[n + 1][m + 1];
for (int i = 1; i <= n; i++){
for (int j = 1; j <= m; j++){
cin>>d[i][j];
}
}
auto adj = [&](int i, int j){
vector<pii> out;
if (i > 1){
out.push_back({i - 1, j});
}
if (j > 1){
out.push_back({i, j - 1});
}
if (i < n){
out.push_back({i + 1, j});
}
if (j < m){
out.push_back({i, j + 1});
}
return out;
};
auto solve = [&](int i, int j){
queue<node> q;
node st(i, j);
q.push(st);
int out = 0;
while (!q.empty()){
node cur = q.front(); q.pop();
// cout<<cur.x<<" "<<cur.y<<"\n";
if (cur.x == 1 || cur.x == n || cur.y == 1 || cur.y == m){
out = max(out, cur.sum);
}
for (auto [x, y]: adj(cur.x, cur.y)){
if (cur.sum + 1 > d[x][y]) continue;
node nw = cur;
nw.x = x;
nw.y = y;
nw.sum++;
nw.mp[{x, y}] = true;
q.push(nw);
}
}
return out;
};
int out = 0;
for (int i = 1; i <= n; i++){
out = max(out, solve(i, 1));
out = max(out, solve(i, m));
}
for (int j = 1; j <= m; j++){
out = max(out, solve(1, j));
out = max(out, solve(n, j));
}
cout<<out;
}