import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.PriorityQueue; public class Main { public static void main(String[] args) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] sa = br.readLine().split(" "); int h = Integer.parseInt(sa[0]); int w = Integer.parseInt(sa[1]); int[][] a = new int[h][w]; for (int i = 0; i < h; i++) { sa = br.readLine().split(" "); for (int j = 0; j < w; j++) { a[i][j] = Integer.parseInt(sa[j]); } } br.close(); int hw = h * w; boolean[] b1 = new boolean[hw]; boolean[] b2 = new boolean[hw]; int[] c = new int[hw]; b1[0] = true; b2[hw - 1] = true; c[0] = 1; c[hw - 1] = 2; PriorityQueue que1 = new PriorityQueue(); PriorityQueue que2 = new PriorityQueue(); que1.add(new Node(0, 1, 0)); que2.add(new Node(hw - 1, 2, 0)); int ans = -2; int[] dx = {1, 0, -1, 0}; int[] dy = {0, 1, 0, -1}; label: while (!que1.isEmpty() && !que2.isEmpty()) { Node cur = que1.poll(); int cx = cur.v / w; int cy = cur.v % w; c[cur.v] = cur.a; ans++; for (int i = 0; i < 4; i++) { int nx = cx + dx[i]; int ny = cy + dy[i]; if (nx < 0 || h <= nx || ny < 0 || w <= ny) { continue; } int next = nx * w + ny; if (!b1[next]) { que1.add(new Node(next, cur.a, a[nx][ny])); b1[next] = true; } if (c[next] == 2) { break label; } } cur = que2.poll(); cx = cur.v / w; cy = cur.v % w; c[cur.v] = cur.a; ans++; for (int i = 0; i < 4; i++) { int nx = cx + dx[i]; int ny = cy + dy[i]; if (nx < 0 || h <= nx || ny < 0 || w <= ny) { continue; } int next = nx * w + ny; if (!b2[next]) { que2.add(new Node(next, cur.a, a[nx][ny])); b2[next] = true; } if (c[next] == 1) { break label; } } } System.out.println(ans); } static class Node implements Comparable { int v, a; long d; public Node(int v, int a, long d) { this.v = v; this.a = a; this.d = d; } public int compareTo(Node o) { return Long.compare(d, o.d); } } }