[백준/C++/Graph] 16928 뱀과 사다리 게임

2024. 7. 28. 10:59·[ Computer Science ]/Algorithm_C++

0. 풀이한 문제

뱀과 사다리 게임 / 골5 / 16928 / bfs

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

 

1. 테스트 케이스 분석

백준에 있는 예시는 너무 길고 많아서 간단하게 확인할 예제를 chat gpt에 물어보고 활용했다

 

gpt가 알려준 예제는

사다리 2->15 ,  5 -> 7

뱀 17 -> 3

이다

 

이동을 시작하기 전 초기 상태를 0번째 단계라고 하면

0번째 단계에서 시작 위치는 1이고 누적 거리 합은 0 이다

시작 위치는 백준에서 범위 값을 0이 아닌 1부터로 했기 때문에 1이고

최단 거리를 리턴해야하므로 누적 거리 합을 체크하는 부분이 필요해서

현재 위치와 누적 거리 합을 하나의 쌍으로 묶어서 생각했다

 

현재 위치인 1에서 이동할 수 있는 거리는

주사위 1~6까지 중 하나의 값을 더해서 나오는 값이므로 

2~7까지 이동 가능하다

 

큐에 이동할 수 있는 2~7을 넣어주어야 하는데

이때 누적 이동 거리는 주사위 한 번으로 이동한 것이니 1이다

 

큐에 삽입하려고 할 때 

2와 5 좌표에서는 사다리가 있어서 무조건 이동해야하니

최종 좌표는 15와 17이 되고

사다리를 통해 이동하는 거리는 카운트 되지 않으니 누적 이동 거리 합은 여전히 1이다

 

 

첫 이동을 끝낸 상태의 큐이다

큐에는 시작 위치 1에서 주사위로 이동할 수 있는 좌표로 이동한 후 

사다리가 있는 곳은 사다리 이동까지 한 후 

최종 좌표를 큐에 삽입한 상태이다

 

bfs로 탐색하는 것이므로 방문한 좌표는 

다시 방문하지 않기 위해 visited 배열을 true로 바꿔서

재방문하지 않도록 처리한다

 

큐에서 하나씩 꺼내서 이동할 수 있는 좌표를 더 탐색한다

일단 첫번째 요소인 (15, 1) 을 큐에서 pop할 것이다

 

(15, 1) 에서 주사위로 이동할 수 있는 좌표는 1~6을 더한 16~21이다

누적 거리 합이 1인 좌표에서 한 칸 더 이동하는 것이므로

16~21은 누적 거리 합이 2일 것이다

 

해당 범위에서 무조건 이동해야하는 뱀은 17 -> 3이 있으므로

17로 이동하는 좌표는 최종적으로 큐에 삽입될 때는 3이 될 것이다

 

큐에 이미 좌표가 3일 때 누적 거리 합이 1인 경우가 있지만

지금 추가하게 되는 것은 거리 합이 2인 경우로 다른 쌍이기 때문에

갱신하지 않고 추가한다

 

방문하게 되는 모든 인덱스는 또 true로 바꾸어 방문 처리한다

 

세 번째 단계에서는 다음 차례인 (3,1) 값을 꺼내서 같은 과정을 또 반복한다

반복하다가 현재 위치가 100일 때 누적 거리 합을 리턴하면 된다

 

2. 코드

코드는 인접 행렬과 인접 리스트 두 가지 방법으로 작성해서 

함수가 두 개이다

함수를 호출하는 두 가지 문장 중 하나만 주석처리하면

백준에서 정답 처리된다

#include <iostream>
#include <queue>
#include <vector>
#include <cstring>

using namespace std;

const int MAX = 100;
int board[MAX + 1]; // 보드 (1번 칸부터 100번 칸까지)
// 각 인덱스 칸에서 뱀이나 사다리를 타고 이동할 칸을 저장
// 뱀이나 사다리로 연결된 칸이 없으면 0

// 인접 행렬
int bfs_matrix() {
    bool visited[MAX + 1]; // 방문 여부
    memset(visited, false, sizeof(visited));

    queue<pair<int, int>> q; // (현재 위치, 주사위 던진 횟수)
    q.push({1, 0});
    visited[1] = true;

    while (!q.empty()) {
        int current = q.front().first;
        int moves = q.front().second;
        q.pop();

        if (current == 100) {
            return moves;
        }

        for (int dice = 1; dice <= 6; dice++) {
            int next = current + dice;

            if (next <= 100 && !visited[next]) {
                visited[next] = true;
                if (board[next] != 0) {
                    next = board[next];
                }
                q.push({next, moves + 1});
            }
        }
    }

    return -1; // 도달 불가능한 경우
}

// 인접 리스트
int bfs_list() {
    bool visited[MAX + 1]; // 방문 여부
    memset(visited, false, sizeof(visited));

    queue<pair<int, int>> q; // (현재 위치, 주사위 던진 횟수)
    q.push({1, 0});
    visited[1] = true;

    while (!q.empty()) {
        int current = q.front().first;
        int moves = q.front().second;
        q.pop();

        if (current == 100) {
            return moves;
        }

        for (int dice = 1; dice <= 6; dice++) {
            int next = current + dice;

            if (next <= 100 && !visited[next]) {
                visited[next] = true;
                if (board[next] != 0) {
                    next = board[next];
                }
                q.push({next, moves + 1});
            }
        }
    }

    return -1; // 도달 불가능
}

int main() {
    int n, m;
    cin >> n >> m;

    // 보드 초기화
    memset(board, 0, sizeof(board));

    // 사다리와 뱀 정보 입력
    for (int i = 0; i < n + m; i++) {
        int start, end;
        cin >> start >> end;
        board[start] = end;
    }

    // 최소 주사위 던진 횟수 계산
    int result;

    result = bfs_matrix(); // 인접 행렬
    // result = bfs_list(); // 인접 리스트

    // 결과 출력
    cout << result << endl;

    return 0;
}

 

728x90

'[ Computer Science ] > Algorithm_C++' 카테고리의 다른 글

[백준/C++/Greedy] 13305 주유소  (1) 2024.08.19
[백준/C++/Greedy] 11399 ATM  (0) 2024.08.19
[백준/C++/Greedy] 11047 동전 0  (0) 2024.08.19
[백준/C++/DP] 1463 1로 만들기  (0) 2024.06.28
[프로그래머스/C++] 주사위 게임 3  (0) 2024.02.04
[프로그래머스/C++] 연속된 수의 합  (0) 2024.02.04
[프로그래머스/C++] 최빈값 구하기  (0) 2024.02.04
'[ Computer Science ]/Algorithm_C++' 카테고리의 다른 글
  • [백준/C++/Greedy] 11399 ATM
  • [백준/C++/Greedy] 11047 동전 0
  • [백준/C++/DP] 1463 1로 만들기
  • [프로그래머스/C++] 주사위 게임 3
dev charlotte
dev charlotte
주 - 컴퓨터공학 / 복수 - 산업 보안
    250x250
  • dev charlotte
    int main() {
    dev charlotte
  • 전체
    오늘
    어제
    • 분류 전체보기
      • [ Laboratory ]
        • Paper review
        • Advanced Operating System
        • System Software & Storage
        • Lab etc
      • [ Computer Science ]
        • Algorithm_C++
        • Operating System
        • Information Retrieval
        • Database_sql
        • SW Engineering
        • Computer Network
        • JavaScript
        • Python
        • Data Structure
        • CS study
        • Distributed systems
      • [ Computer Security ]
        • Convergence Security
        • Web Security
        • PIMS
        • Network Security
        • Digital Finance
      • [ Artificial Intelligence ]
        • Trend
        • Seminar
      • [ 미래, 같이, LG ]
      • [ Development ]
        • [ Front-end ]
        • [ Back-end ] Spring 기본
        • [ Back-end ] Node.js
      • etc
        • 현대오토에버 스마트 모빌리티 공학 체험 교육
      • It's me
  • 블로그 메뉴

    • 링크

      • GitHub
    • 공지사항

    • 인기 글

    • 태그

      프로그래밍 언어론
      SQL
      데이터베이스
      SQL 쿼리
      현대오토에버 스마트 모빌리티
      프로그래머스 코테
      싸피
      코딩 교육
      백준
      대학생 대외활동
      오블완
      비전공자 코딩
      코딩 인강
      hotstorage
      spdk
      소프트웨어 공학
      싸피 13기
      자바스크립트
      프로그래머스 입문
      SSAFY
      MySQL
      티스토리챌린지
      프로그래머스 c++
      현대오토에버
      ssafy 13기
      현대오토에버 스마트모빌리티
      공대생 대외활동
      코드잇
      스마트모빌리티공학체험교육
      프로그래머스
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.4
    dev charlotte
    [백준/C++/Graph] 16928 뱀과 사다리 게임
    상단으로

    티스토리툴바