

import java.util.*;
import java.io.*;
public class Main {
static int[] dx = {-1,0,1,0};
static int[] dy = {0,1,0,-1};
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine()," ");
int M = Integer.parseInt(st.nextToken());
int N = Integer.parseInt(st.nextToken());
int[][] board = new int[N][M];
Queue<int[]> q = new LinkedList<int[]>();
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine()," ");
for (int j = 0; j < M; j++) {
int val = Integer.parseInt(st.nextToken());
if(val == 1) {
board[i][j] = Integer.MIN_VALUE; // 시작점 1과, 1일차 1을 구분하기 위해
int[] temp = {i,j};
q.add(temp);
}else {
board[i][j] = val;
}
}
}
// 정답코드: BFS를 실행해야 하는 좌표를 q에 넣어 한번에 BFS에 넣음
BFS(N,M,board,q);
// 시간초과코드: BFS의 좌표 하나하나를 BFS에 넣음
// while(!lst.isEmpty()) {
// BFS(lst.poll(),N,M,board);
// }
int answer = 0;
Here: for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if(board[i][j] == 0) {
answer = -1;
break Here;
}
answer = Math.max(answer, board[i][j]);
}
}
System.out.println(answer);
}
public static void BFS(int N, int M , int[][] board,Queue<int[]> q) {
// 시간초과 코드
// Queue<int[]> q = new LinkedList<int[]>();
// q.offer(start);
int cnt = 0;
while(! q.isEmpty()) {
// 진행과정 확인코드 -> 주석을 풀고 눈으로 보는걸 추천드립니다.
// for (int i = 0; i < board.length; i++) {
// System.out.println(Arrays.toString(board[i]));
// }
// System.out.println("=========");
int size = q.size();
cnt++;
while(--size>=0) {
int[] temp = q.poll();
int x = temp[0];
int y = temp[1];
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if(0<= nx && nx < N && 0<= ny && ny < M && (board[nx][ny] == 0 || board[nx][ny] > cnt)) { // 정답코드에서는 board[nx][ny] > cnt는 필요없습니다.
board[nx][ny] = cnt;
int[] temp2 = {nx,ny};
q.offer(temp2);
}
}
}
}
}
}