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;
using System.Text;
using System.Threading.Tasks;

namespace AGC033A7
{
    class Program
    {
        static int black = 0;
        static int white = 1;
        static int[,] A;
        static int[] dp;
        static int max;
        static int tmp;
        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]);//１文字目を数値化してhに代入する
            int w = int.Parse(input[1]);//２文字目を数値化してwに代入する
            A = new int[h, w];
            dp = new int[h * w];
            max = h + w - 1;//答えの最大値+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 == "#")
                    {
                        A[i, j] = black;
                        dp[i * h + j] = black;
                        pos p = new pos();
                        p.x = i;
                        p.y = j;
                        C_list.Add(p);
                    }
                    else
                    {
                        A[i, j] = white;
                        dp[i * h + j] = max;
                    }
                }
            }
            int r = 0;
            while (dp.Max() == max)
            {
                List<pos> C2_list = new List<pos>(C_list);
                if (C2_list.Count > 0)
                {
                    foreach (var item in C2_list)
                    {
                        seek(item.x, item.y, h, w, r);
                    }
                    C2_list.Clear();
                }
                r++;
            }
            /*
            for (int i = 0; i < h; i++)
            {
                for (int j = 0; j < w; j++)
                {
                    Console.Write(dp[i * h + j] + " ");
                }
                Console.WriteLine();
            }
            */
            Console.WriteLine(dp.Max());

        }
        static void seek(int i, int j, int h, int w, int r)
        {
            tmp = dp[i * h + j];
            if (i > 0)
            {
                if (dp[i * h + j] == r && dp[(i - 1) * h + j] == max)
                {
                    dp[(i - 1) * h + j] = tmp + 1;
                    pos p = new pos();
                    p.x = i - 1;
                    p.y = j;
                    C_list.Add(p);
                }
            }
            if (i < h - 1)
            {
                if (dp[i * h + j] == r && dp[(i + 1) * h + j] == max)
                {
                    dp[(i + 1) * h + j] = tmp + 1;
                    pos p = new pos();
                    p.x = i + 1;
                    p.y = j;
                    C_list.Add(p);
                }
            }
            if (j > 0)
            {
                if (dp[i * h + j] == r && dp[i * h + j - 1] == max)
                {
                    dp[i * h + j - 1] = tmp + 1;
                    pos p = new pos();
                    p.x = i;
                    p.y = j - 1;
                    C_list.Add(p);
                }
            }
            if (j < w - 1)
            {
                if (dp[i * h + j] == r && dp[i * h + j + 1] == max)
                {
                    dp[i * h + j + 1] = tmp + 1;
                    pos p = new pos();
                    p.x = i;
                    p.y = j + 1;
                    C_list.Add(p);
                }
            }
        }
    }
}