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 AGC033A8
{
    class Program
    {
        public static int black = 0;
        //public static int[,] dp;
        static int[,] dp;
        public static int max;
        public static int ans = 0;
        public struct pos
        {
            public int x;
            public int y;
        }
        public static List<pos> C_list = new List<pos>();
        static void Main(string[] args)
        {
            string[] input = Console.ReadLine().Split(' ');
            int h = int.Parse(input[0]);
            int w = int.Parse(input[1]);
            dp = new int[h , w];
            max = h + w - 1;//答えの最大値+1　最大の答えは(h-1)+(w-1)

            for (int i = 0; i < h; i++)
            {
                var tmp = Console.ReadLine();
                for (int j = 0; j < w; j++)
                {
                    var tmp2 = tmp.Substring(j, 1);
                    if (tmp2 == "#")
                    {
                        dp[i ,j] = black;
                        pos p = new pos();
                        p.x = i;
                        p.y = j;
                        C_list.Add(p);//黒コマの場所をリストにする
                    }
                    else
                    {
                        dp[i,j] = max;
                    }
                }
            }
            while (C_list.Count > 0)
            {
                List<pos> C2_list = new List<pos>(C_list);
                C_list.Clear();
                foreach (var item in C2_list)
                {
                    seek(item.x, item.y, h, w);//周囲をチェック
                }
                /*
                for (int i = 0; i < h; i++)
                {
                    for (int j = 0; j < w; j++)
                    {
                        Console.Write(dp[i * h + j] + " ");
                    }
                    Console.WriteLine();
                }
                Console.WriteLine();
*/
            }
            Console.WriteLine(ans);
        }
        static void seek(int i, int j, int h, int w)
        {
            pos p = new pos();
            if (i > 0 && dp[(i - 1) , j] == max)
            {
                dp[(i - 1) , j] = dp[i , j] + 1;
                p.x = i - 1;
                p.y = j;
                ans = Math.Max(ans, dp[(i - 1) , j]);
                C_list.Add(p);
            }
            if (i < h - 1 && dp[(i + 1) , j] == max)
            {
                dp[(i + 1) , j] = dp[i , j] + 1;
                p.x = i + 1;
                p.y = j;
                ans = Math.Max(ans, dp[(i + 1) , j]);
                C_list.Add(p);
            }
            if (j > 0 && dp[i ,j- 1] == max)
            {
                dp[i , j - 1] = dp[i , j] + 1;
                p.x = i;
                p.y = j - 1;
                ans = Math.Max(ans, dp[i , j - 1]);
                C_list.Add(p);
            }
            if (j < w - 1 && dp[i , j + 1] == max)
            {
                dp[i , j + 1] = dp[i , j] + 1;
                p.x = i;
                p.y = j + 1;
                ans = Math.Max(ans, dp[i , j + 1]);
                C_list.Add(p);
            }
        }
    }
}