문제 링크 (opens new window)

# 풀이

  1. 해셔블 Coordinate 구조체 타입 정의
  2. 좌표 변화량 정의, 대각선까지 포함하여 총 8개
  3. 방문배열 정의, 벽이 내려오는 것은 8번까지만 해당함. 이후에는 벽이 아예 없는채로 진행된다
    • 자리에서 대기한 회차 기반으로 방문배열 데이터를 관리한다.
  4. 큐에 방문한 좌표와 벽이 내려온 횟수를 추가한다.
import Foundation

struct Queue<T> {
    var array: [T?] = []
    var head = 0

    var isEmpty: Bool {
        return count == 0
    }

    var count: Int {
        return array.count - head
    }

    mutating func enqueue(_ element: T) {
        array.append(element)
    }

    mutating func dequeue() -> T? {
        guard head < array.count,
              let element = array[head] else { return nil }

        array[head] = nil
        head += 1

        if Double(head) / Double(array.count) > 0.25 && array.count > 50 {
            array.removeFirst(head)
            head = 0
        }

        return element
    }

    var front: T? {
        if isEmpty {
            return nil
        } else {
            return array[head]
        }
    }
}

struct Coordinate: Hashable {
    let y: Int
    let x: Int
}

let dy = [-1, -1, 0, 1, 1, 1, 0, -1]
let dx = [0, 1, 1, 1, 0, -1, -1, -1]
var adj: [[String]] = .init(repeating: .init(repeating: ".", count: 8), count: 8)
var visited: [[[Bool]]] = Array(repeating: Array(repeating: Array(repeating: false, count: 8), count: 8), count: 8)

for i in 0..<8 {
    adj[i] = readLine()!.map { String($0) }
}

var q = Queue<(Coordinate, Int)>()
q.enqueue((Coordinate(y: 7, x: 0), 0))
visited[0][7][0] = true

var flag = false

while !q.isEmpty {
    let qSize = q.count

    for _ in 0..<qSize {
        guard let (current, time) = q.dequeue() else { break }
        let (here, t) = (current, min(time, 7))

        if adj[here.y][here.x] == "#" { continue }

        if here.y == 0 && here.x == 7 {
            flag = true
            break
        }

        q.enqueue((Coordinate(y: here.y, x: here.x), t + 1))
        visited[t][here.y][here.x] = true

        for i in 0..<8 {
            let ny = dy[i] + here.y
            let nx = dx[i] + here.x

            if ny < 0 || nx < 0 || ny >= 8 || nx >= 8 || visited[t][ny][nx] || adj[ny][nx] == "#" {
                continue
            }

            q.enqueue((Coordinate(y: ny, x: nx), t + 1))
            visited[t][ny][nx] = true
        }
    }

    if flag { break }

    // 벽 움직이기
    adj.insert(.init(repeating: ".", count: 8), at: 0)
    _ = adj.popLast()
}
print(flag ? 1 : 0)