Problem:
Score : 300 points

Problem Statement

You are given a grid of squares with H horizontal rows and W vertical columns, where each square is painted white or black.
HW characters from A_{11} to A_{HW} represent the colors of the squares.
A_{ij} is # if the square at the i-th row from the top and the j-th column from the left is black, and A_{ij} is . if that square is white.

We will repeatedly perform the following operation until all the squares are black:

Every white square that shares a side with a black square, becomes black.

Find the number of operations that will be performed.
The initial grid has at least one black square.

Constraints

1 \leq H,W \leq 1000

A_{ij} is # or ..

The given grid has at least one black square.

Input

Input is given from Standard Input in the following format:

H W
A_{11}A_{12}...A_{1W}
:
A_{H1}A_{H2}...A_{HW}

Output

Print the number of operations that will be performed.

Sample Input 1

3 3
...
.#.
...

Sample Output 1

2

After one operation, all but the corners of the grid will be black. After one more operation, all the squares will be black.

Sample Input 2

6 6
..#..#
......
#..#..
......
.#....
....#.

Sample Output 2

3

Solution in Java7 (OpenJDK 1.7.0) (judge verdict: Time Limit Exceeded)

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Scanner;

public class Main  implements Runnable { //Runnableを実装する

    public static void main(String[] args) {

        new Thread(null, new Main(), "", 16 * 1024 * 1024).start(); //16MBスタックを確保して実行

    }

    public void run() {
		Scanner sc = new Scanner(System.in);
		//Scanner sc = new Scanner("3 3 ... .#. ...");
		int h = Integer.parseInt(sc.next());
		int w = Integer.parseInt(sc.next());
		//int b = Integer.parseInt(sc.next());
		//int t = Integer.parseInt(sc.next());
		//int k = 0;
		//int k = Integer.parseInt(sc.next());
		//String str = sc.next();
		//char c[] = str.toCharArray();
		char a[][] = new char[h][w];
		char anext[][] = new char[h][w];
		int atmp[] = new int[h];
		int max= 0;
		for (int i = 0; i < h; i++)
		{
				a[i]= sc.next().toCharArray();
		}
		for(int k = 0; k < 2000; k++)
		{
		    for (int i=0; i < h; i++) {
		        System.arraycopy(a[i], 0, anext[i], 0, w);
		    }
		    int hap = 0;
			for (int i = 0; i < h; i++)
			{
				for (int j = 0; j < w; j++)
				{
					if(a[i][j] == '.')
					{
						if(i-1>=0)
						{
							if (a[i-1][j] == '#')
							{
								anext[i][j] = '#';
								hap=1;
							}
						}
						if(j-1>=0)
						{
							if (a[i][j-1] == '#')
							{
								anext[i][j] = '#';
								hap=1;
							}
						}
						if(i+1<h)
						{
							if (a[i+1][j] == '#')
							{
								anext[i][j] = '#';
								hap=1;
							}
						}
						if(j+1<w)
						{
							if (a[i][j+1] == '#')
							{
								anext[i][j] = '#';
								hap=1;
							}
						}
					}
				}
			}
			if(hap ==1)
			{
				max++;
			}
		    for (int i=0; i < h; i++) {
		        System.arraycopy(anext[i], 0, a[i], 0, w);
		    }
			
		}

		int ans = max;
		PrintWriter out = new PrintWriter(System.out);
		out.println(ans);
		out.flush();
	}
    private static int gcd(int m, int n) {
        if(m < n)
        {
        	return gcd(n, m);
        }
        if(n==0)
        {
        	return m;
        }
        return gcd(n, m % n);
    }
}