module main; // https://yukicoder.me/submissions/16998 より // 2次元グリッド、幅優先探索 import std; // C++ の tie auto tie(StoreElements...)(ref StoreElements stores) { alias Elements = staticMap!(Unqual, StoreElements); template toPointer(T) { alias toPointer = T*; } struct Holder { alias StoreElementsPtrs = staticMap!(toPointer, StoreElements); StoreElementsPtrs storePtrs; this(ref StoreElements stores) { foreach(i, _; StoreElements) { storePtrs[i] = &stores[i]; } } void opAssign(Tuple!Elements values) { foreach(i, _; Elements) { *storePtrs[i] = values[i]; } } } return Holder(stores); } void main() { // 入力 int W, H; readln.chomp.formattedRead("%d %d", W, H); auto board = new string[](H); foreach (ref row; board) row = readln.chomp; // 答えの計算と出力 auto check = new bool[][](H, W); alias P = Tuple!(int, "y", int, "x"); auto que = DList!P(); foreach (i; 0 .. H) { foreach (j; 0 .. W) { if (board[i][j] == '#') continue; check[i][j] = true; que.insertBack(P(i, j)); break; } if (!que.empty) break; } auto dir = [P(1, 0), P(0, 1), P(-1, 0), P(0, -1)]; while (!que.empty) { int y, x; tie(y, x) = que.front; que.removeFront; foreach (d; dir) { int ny = y + d.y; int nx = x + d.x; if (ny < 0 || ny >= H || nx < 0 || nx >= W) continue; if (check[ny][nx]) continue; if (board[ny][nx] == '#') continue; check[ny][nx] = true; que.insertBack(P(ny, nx)); } } auto dist = new int[][](H, W); foreach (i; 0 .. H) { foreach (j; 0 .. W) { if (board[i][j] == '.' && !check[i][j]) { check[i][j] = true; que.insertBack(P(i, j)); dist[i][j] = 0; } else dist[i][j] = 999; } } while (!que.empty) { int y, x; tie(y, x) = que.front; que.removeFront; foreach (d; dir) { int ny = y + d.y; int nx = x + d.x; if (ny < 0 || ny >= H || nx < 0 || nx >= W) continue; if (dist[ny][nx] < 999) continue; if (board[ny][nx] == '.') { writeln(dist[y][x]); return; } que.insertBack(P(ny, nx)); dist[ny][nx] = dist[y][x] + 1; } } }