import Foundation public struct Deque { private var array: [T?] private var head: Int private var capacity: Int private let originalCapacity: Int public init(_ capacity: Int = 10) { self.capacity = max(capacity, 1) originalCapacity = self.capacity array = [T?](repeating: nil, count: capacity) head = capacity } public var isEmpty: Bool { return count == 0 } public var count: Int { return array.count - head } public mutating func enqueue(_ element: T) { array.append(element) } public mutating func enqueueFront(_ element: T) { if head == 0 { capacity *= 2 let emptySpace = [T?](repeating: nil, count: capacity) array.insert(contentsOf: emptySpace, at: 0) head = capacity } head -= 1 array[head] = element } public mutating func dequeue() -> T? { guard head < array.count, let element = array[head] else { return nil } array[head] = nil head += 1 if capacity >= originalCapacity && head >= capacity*2 { let amountToRemove = capacity + capacity/2 array.removeFirst(amountToRemove) head -= amountToRemove capacity /= 2 } return element } public mutating func dequeueBack() -> T? { if isEmpty { return nil } else { return array.removeLast() } } public func peekFront() -> T? { if isEmpty { return nil } else { return array[head] } } public func peekBack() -> T? { if isEmpty { return nil } else { return array.last! } } } func readInt() -> [Int] { return readLine()!.split(separator: " ").map{Int($0)!} } let line = readInt() let W = line[0] let H = line[1] let maze = (1...H).map { _ in Array(readLine()!) } let directions = [(1,0),(0,1),(-1,0),(0,-1)] func holeCheck(_ y: Int, _ x: Int, _ hole: Set<[Int]>) -> Bool { return y < 0 || y >= H || x < 0 || x >= W || maze[y][x] == "#" || hole.contains([y, x]) } func gridCheck(_ y: Int, _ x: Int, _ hole: Set<[Int]>) -> Bool { return y < 0 || y >= H || x < 0 || x >= W || hole.contains([y, x]) } func bfs(_ initial: [Int], _ hole: inout Set<[Int]>, _ goal: (Int, Int) -> Bool, _ isOut: (Int, Int, Set<[Int]>) -> Bool) -> Int { var queue = Deque<[Int]>() queue.enqueue(initial) var explored = Set<[Int]>() explored.insert([initial[0], initial[1]]) hole.insert([initial[0], initial[1]]) while let yx = queue.dequeue() { let y = yx[0] let x = yx[1] let count = yx[2] for d in directions { let y_ = d.0 + y let x_ = d.1 + x if goal(y_, x_) { return count } if isOut(y_, x_, hole) || explored.contains([y_, x_]){ continue } hole.insert([y_, x_]) explored.insert([y_, x_]) queue.enqueue([y_, x_, count+1]) } } return 401 } func main() { var holes = [Set<[Int]>(), Set<[Int]>()] var count = 0 for i in 1..<(H-1) { for j in 1..<(W-1) { if holes.allSatisfy({!$0.contains([i, j])}) && maze[i][j] == "." { let _ = bfs([i,j,0], &holes[count], { _, _ in false }, holeCheck) count += 1 } if count > 1 { break } } if count > 1 { break } } var ans = 401 for yx in holes[0] { var s = Set<[Int]>() let res = bfs([yx[0], yx[1], 0], &s, { holes[1].contains([$0, $1]) }, gridCheck) if res < ans { ans = res } } print(ans) } main()