#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
const int N = 1e3 + 10;
struct node {
int I, J;
};
int n, m;
int a[N][N];
bool vis[N][N];
int x[4] = {-1, 1, 0, 0};
int y[4] = {0, 0, -1, 1};
bool check (int mid) {
memset(vis, false, sizeof(vis));
queue <node> q;
q.push({1, 1});
vis[1][1] = true;
while (!q.empty()) {
node t = q.front();
q.pop();
for (int i = 0; i < 4; i ++) {
int X = x[i] + t.I;
int Y = y[i] + t.J;
if (X <= 0 || Y <= 0 || X > n || Y > m || vis[X][Y] || mid < a[X][Y]) continue;
q.push({X, Y});
vis[X][Y] = true;
if (X == n) return true;
}
} return false;
}
int main () {
cin >> n >> m;
for (int i = 1; i <= n; i ++) {
for (int j = 1; j <= m; j ++) {
cin >> a[i][j];
}
}
int l = 0, r = 1e9;
int mid;
while (l <= r) {
mid = r + l >> 1;
if (check(mid)) r = mid - 1;
else l = mid + 1;
} cout << mid;
return 0;
}