알고리즘/문제 풀이

백준 16928번: 뱀과 사다리 게임

Themion 2022. 1. 13. 11:56

https://www.acmicpc.net/problem/16928

 

16928번: 뱀과 사다리 게임

첫째 줄에 게임판에 있는 사다리의 수 N(1 ≤ N ≤ 15)과 뱀의 수 M(1 ≤ M ≤ 15)이 주어진다. 둘째 줄부터 N개의 줄에는 사다리의 정보를 의미하는 x, y (x < y)가 주어진다. x번 칸에 도착하면, y번 칸으

www.acmicpc.net

각 칸에 도착했을 때 사다리 혹은 뱀에 의해 도달하는 칸을 배열 arrive에 저장한 뒤, 칸 i에서 주사위눈 j가 나온 경우 최종적으로 도착하는 좌표를 v[i][j]에 arrive를 이용해 저장한다. 이후 100번 칸에 도착할 때까지 bfs를 시행하면 주사위를 굴려야 하는 최소 횟수를 얻을 수 있으므로 이를 출력한다.

#include <cstdio>
#include <queue>
#include <vector>

using namespace std;

#define END 100
#define append(i) q.push(i); visit[i] = true;

int main() {
    // visit[i]: 노드 i에 방문한 적이 있다면 true, 아니라면 false
    bool visit[END + 1] = { false, true, };
    // N: 사다리의 수, M: 뱀의 수, s, e: 각 사다리와 뱀의 시작점과 끝점
    // step: 주사위를 굴릴 횟수
    // arrive[i]: 노드 i에 도착했을 때 실제로 도달하게 될 노드
    int N, M, s, e, step = 0, len = 1, arrive[END + 1] = { 0, };
    // bfs에 사용할 큐
    queue<int> q;
    // v[i]: 노드 i에서 주사위를 굴려 갈 수 있는 노드
    vector<int> v[END + 1];

    // arrive[i]의 기본 값을 지정
    for (int i = 1; i <= END; i++) arrive[i] = i;

    // 각 뱀과 사다리의 시작점과 도착점을 입력받은 뒤 이동 관계를 arrive에 저장
    for (scanf("%d %d", &N, &M); N ? N-- : M--; ) {
        scanf("%d %d", &s, &e);
        arrive[s] = e;
    }

    // 각 노드에서 주사위를 굴려 이동 가능한 노드를 계산
    for (int i = 1; i < END; i++) for (int j = 1; j <= 6 && i + j <= END; j++)
        v[i].push_back(arrive[i + j]);

    // 게임은 반드시 1번 노드에서 시작하므로 q에 1을 push
    append(1);

    // 100번 노드에 도착할 때까지 bfs를 실행한 뒤 최소 step을 반환
    while (!visit[END]) {
        if (!--len) {
            len = q.size();
            step++;
        }

        // 도착 가능한 노드를 q에서 가져온 뒤
        s = q.front();
        q.pop();

        // s에서 이동 가능한 노드를 q에 push
        for (int i : v[s]) if (!visit[i]) { append(i); }
    }
    printf("%d\n", step);

    return 0;
}