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: Runtime Error)

using System;
using System.Collections.Generic;
using System.Linq;

namespace AtCoderWorkspace
{
    class Program
    {
        static void Main(string[] args)
        {
            var cin = new Scanner();
            var H = cin.nextInt();
            var W = cin.nextInt();

            int[,] field = new int[H, W];
            var que = new Queue<Tuple<int, int>>();
            for(int i = 0; i < H; i++)
            {
                var row = cin.next().ToArray();
                for(int j = 0; j < W; j++)
                {
                    field[i, j] = row[j] == '#' ?  0 : -1;
                    if (row[j] == '#') que.Enqueue(new Tuple<int, int>(i,j));
                }
            }

            while(que.Count > 0)
            {
                var item = que.Dequeue();
                var i = item.Item1;
                var j = item.Item2;

                // up right down left
                var x = new int[] { 0, 1, 0, -1 };
                var y = new int[] { 1, 0, -1, 0 };

                for(int k = 0; k < x.Count(); k++)
                {
                    var X = j + x[k];
                    var Y = i + y[k];

                    // inner field
                    if(X < W && 0 <= X && Y < H && 0 <= Y)
                    {
                        // not visited node
                        if(field[X,Y] == -1)
                        {
                            field[X, Y] = field[i, j] + 1;
                            que.Enqueue(new Tuple<int, int>(X,Y));
                        }
                    }
                }
            }

            var result = Math.Max(0, field.Cast<int>().ToArray().Max());
            Console.WriteLine(result);
        }

       
    }

    
    class Scanner
    {
        string[] s;
        int i;

        char[] cs = new char[] { ' ' };

        public Scanner()
        {
            s = new string[0];
            i = 0;
        }

        public string next()
        {
            if (i < s.Length) return s[i++];
            string st = Console.ReadLine();
            while (st == "") st = Console.ReadLine();
            s = st.Split(cs, StringSplitOptions.RemoveEmptyEntries);
            if (s.Length == 0) return next();
            i = 0;
            return s[i++];
        }

        public int nextInt()
        {
            return int.Parse(next());
        }
        public int[] ArrayInt(int N, int add = 0)
        {
            int[] Array = new int[N];
            for (int i = 0; i < N; i++)
            {
                Array[i] = nextInt() + add;
            }
            return Array;
        }

        public long nextLong()
        {
            return long.Parse(next());
        }

        public long[] ArrayLong(int N, long add = 0)
        {
            long[] Array = new long[N];
            for (int i = 0; i < N; i++)
            {
                Array[i] = nextLong() + add;
            }
            return Array;
        }

        public double nextDouble()
        {
            return double.Parse(next());
        }


        public double[] ArrayDouble(int N, double add = 0)
        {
            double[] Array = new double[N];
            for (int i = 0; i < N; i++)
            {
                Array[i] = nextDouble() + add;
            }
            return Array;
        }
    }
}