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 Go (1.6) (judge verdict: Accepted)

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

func out(x ...interface{}) {
	fmt.Println(x...)
}

var sc = bufio.NewScanner(os.Stdin)

func getInt() int {
	sc.Scan()
	i, e := strconv.Atoi(sc.Text())
	if e != nil {
		panic(e)
	}
	return i
}

func getString() string {
	sc.Scan()
	return sc.Text()
}

// min, max, asub, absなど基本関数
func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func asub(a, b int) int {
	if a > b {
		return a - b
	}
	return b - a
}

func abs(a int) int {
	if a >= 0 {
		return a
	}
	return -a
}

const inf = 10000

func main() {
	sc.Split(bufio.ScanWords)
	sc.Buffer([]byte{}, 10000)

	H, W := getInt(), getInt()
	dist := make([][]int, H)
	a := make([]string, H)
	for i := 0; i < H; i++ {
		a[i] = getString()
		dist[i] = make([]int, W)
	}

	for y := 0; y < H; y++ {
		t := inf
		for x := 0; x < W; x++ {
			if a[y][x] == '#' {
				t = 0
			}
			dist[y][x] = t
			t++
		}
		t = dist[y][W-1]
		for x := W - 1; x >= 0; x-- {
			if a[y][x] == '#' {
				t = 0
			}
			dist[y][x] = min(dist[y][x], t)
			t++
		}
	}

	// for y := 0; y < H; y++ {
	// 	out(dist[y])
	// }
	// out("----")

	for x := 0; x < W; x++ {
		t := dist[0][x]
		for y := 0; y < H; y++ {
			if a[y][x] == '#' {
				t = 0
			}
			t = min(dist[y][x], t)
			dist[y][x] = t
			t++
		}
		t = dist[H-1][x]
		for y := H - 1; y >= 0; y-- {
			if a[y][x] == '#' {
				t = 0
			}
			t = min(dist[y][x], t)
			dist[y][x] = t
			t++
		}
	}

	// for y := 0; y < H; y++ {
	// 	out(dist[y])
	// }
	ans := 0
	for y := 0; y < H; y++ {
		for x := 0; x < W; x++ {
			ans = max(ans, dist[y][x])
		}
	}
	out(ans)
}