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 C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ProblemA
{
    class Program
    {
        static void Main(string[] args)
        {
            var read = Console.ReadLine().Split(' ').Select(x => int.Parse(x)).ToArray();
            var H = read[0];
            var W = read[1];
            var countWhite = 0;
            var As = new char[H, W];
            var AIndexs = new int[H, W];
            var que = new Queue<Tuple<int, int, int>>();
            for (int i = 0; i < H; i++)
            {
                var readChar = Console.ReadLine().ToString().ToArray();
                for (int j = 0; j < W; j++)
                {
                    //if (readChar[j] == '.') countWhite++;
                    if (readChar[j] == '#') que.Enqueue(Tuple.Create(i, j, 0));
                    As[i, j] = readChar[j];
                    //AIndexs[i, j] = readChar[j] == '.' ? -1 : 0;
                }
            }

            var ret = 0;
            while (que.Count() > 0)
            {
                var q = que.Dequeue();
                var i = q.Item1;
                var j = q.Item2;
                var c = q.Item3;

                if(i!=0&&As[i - 1,j] == '.')
                {
                    As[i - 1, j] = '#';
                    que.Enqueue(Tuple.Create(i - 1, j, c + 1));
                }
                if (i != H-1 && As[i + 1, j] == '.')
                {
                    As[i + 1, j] = '#';
                    que.Enqueue(Tuple.Create(i + 1, j, c + 1));
                }

                if (j != 0 && As[i , j-1] == '.')
                {
                    As[i , j-1] = '#';
                    que.Enqueue(Tuple.Create(i , j-1, c + 1));
                }

                if (j != W-1 && As[i , j+1] == '.')
                {
                    As[i , j+1] = '#';
                    que.Enqueue(Tuple.Create(i , j+1, c + 1));
                }
                if (que.Count() == 0) ret = c;
            }
            Console.WriteLine(ret);
        }
    }
}