Blog / Algorithm / 백준 16954번 움직이는 미로 탈출 — BFS DFS C++ 풀이
Algorithm

백준 16954번 움직이는 미로 탈출 — BFS DFS C++ 풀이

백준 16954번 움직이는 미로 탈출 풀이. 벽이 매 턴 아래로 내려오는 8×8 미로에서 9방향 이동과 벽 이동 순서를 처리해 탈출 가능 여부를 판별하는 BFS/DFS C++ 코드를 정리한다.

문제

BOJ 16954 - 움직이는 미로 탈출

8×8 체스판에서 벽이 매 턴 한 칸씩 아래로 내려온다. 왼쪽 아래(7,0)에서 오른쪽 위(0,7)로 이동할 수 있는지 판별하는 문제다.

핵심 아이디어

  1. 캐릭터는 상하좌우 + 대각선 + 제자리, 총 9방향으로 이동 가능하다.
  2. 캐릭터 이동 → 벽 이동 → 생존 체크 순서로 진행된다.
  3. 모든 벽이 사라지면 반드시 도달 가능하므로 return 1.
  4. 8×8 고정 크기이므로 DFS로도 시간 내에 풀 수 있다.

풀이

#include <iostream>
#include <vector>

using namespace std;

struct Vector { int x, y; };

Vector directions[9] = {
    {0,0}, {1,0}, {1,1}, {1,-1},
    {-1,0}, {-1,1}, {-1,-1}, {0,1}, {0,-1}
};

bool is_remain_walls(vector<vector<char>>& field) {
    for (int i = 0; i < 8; i++)
        for (int j = 0; j < 8; j++)
            if (field[7 - i][j] == '#') return true;
    return false;
}

bool is_alive(vector<vector<char>>& field, Vector pos) {
    return field[pos.y][pos.x] == '.';
}

void move_wall(vector<vector<char>>& field) {
    for (int i = 0; i < 7; i++)
        for (int j = 0; j < 8; j++)
            field[7 - i][j] = field[7 - i - 1][j];

    for (int i = 0; i < 8; i++)
        field[0][i] = '.';
}

int solution(vector<vector<char>> field, Vector pos,
             bool is_wall_move = true) {
    if (is_wall_move) move_wall(field);
    if (!is_alive(field, pos)) return 0;
    if (!is_remain_walls(field)) return 1;

    int ret = 0;

    for (int i = 0; i < 9; i++) {
        Vector next = {pos.x + directions[i].x,
                       pos.y + directions[i].y};

        if (next.x < 0 || next.y < 0 ||
            next.x >= 8 || next.y >= 8) continue;
        if (field[next.y][next.x] == '#') continue;
        if (!is_alive(field, next)) continue;

        ret |= solution(field, next);
    }

    return ret;
}

int main() {
    vector<vector<char>> field(8, vector<char>(8, ' '));

    for (int i = 0; i < 8; i++)
        for (int j = 0; j < 8; j++)
            cin >> field[i][j];

    cout << solution(field, {0, 7}, false) << endl;

    return 0;
}

주요 포인트

  • field값 복사로 넘겨서 각 분기마다 독립적인 상태를 유지한다.
  • ret |= solution(...) — 하나라도 성공하면 1을 반환한다.
  • 벽은 최대 8턴 후 모두 사라지므로 탐색 깊이가 제한적이다.
  • 시작 위치 {0, 7}은 왼쪽 아래를 의미한다 (x=0, y=7).

복잡도

  • 시간: O(9^8) — 최악의 경우, 실제로는 가지치기로 훨씬 적음
  • 공간: O(8 × 8 × depth) — 재귀마다 field 복사

고정 크기 맵에서의 완전 탐색, 상태 복사와 벽 이동 순서를 정확히 구현하는 것이 관건이다.

댓글

블로그 목록으로
ACHIEVEMENT UNLOCKED
LOADING...
SCORE 000000
HITS
0