ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [13913] 숨바꼭질 4
    BOJ 2021. 9. 1. 20:44

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

     

    13913번: 숨바꼭질 4

    수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일

    www.acmicpc.net

    <문제>

    BFS + 최적해 역추적을 요구하는, 좋은 문제이다.

    문제 이름은 "숨바꼭질 4"지만 1~3을 모두 포함하는 문제는 아니다.

    숨바꼭질 1 : 최적해
    숨바꼭질 2 : 최적해+ 최적해의 개수
    숨바꼭질 3 : 변형 BFS (1/2/4와는 성질이 다르다)
    숨바꼭질 4 : 최적해 + 최적해 역추적

    그렇기에 BFS를 연습하려면 2,3,4는 다 풀어봐야 하겠다. 좋은 문제이니 여러번 봐도 좋을듯 싶다.

    입력으로 N과 K가 주어지고,

    N에 +1, -1, *2의 연산을 최소로 가해 K를 만들면 된다. 사실 이문제는 역추적이 주로 문제가 된다.

     

    path[]를 하나 만들어, 이 선형 자료구조에 '이전의 위치'를 저장할 것이다.

    큐에 삽입할 모든 수를 하나의 정점으로 보고, 이 정점을 방문하기 직전에 방문한 노드의 번호를 저장한단 뜻이다.

    실제로 최적해를 찾은 다음에는 최적해부터 시작위치 N까지 역으로 거슬러 올라올 것이다.

    마지막 위치(K)는 그 이전의 노드번호를, 그 이전의 노드의 path에는 다시 그 이전의 노드번호를 저장하고

    이 과정을 재귀나 반복문(보통 while로 한다)으로 구현하면 된다.

    path를 애초에 전역으로 선언하거나, 0으로 초기화해두면

    while(path!=0) -> 이전의 정점이 존재할동안 반복.. 이런식으로 작성이 가능하다.

    그게 아니라면 while(cur이 N이 아닐동안)... 이렇게도 작성할 수 있고, 재귀함수로 작성하는것도 가능하다.

    <소스코드>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    #include<stdio.h>
    #include<queue>
    #include<stack>
    #include<algorithm>
    using namespace std;
    queue <pair<intint>> q;
    const int SIZE = 250001;
    int n, k,cur,min_cnt,cnt;
    bool visit[250003];
    int path[250003];
     
    int main(void) {
        scanf("%d %d"&n, &k);
        if (n == k) {
            printf("0\n%d", n);
            return 0;
        }
        if (n > k) {
            printf("%d\n", n - k);
            for (int i = n; i >= k; i--) {
                printf("%d ", i);
            }
            return 0;
        }
        q.push(make_pair(n, 0));
        visit[n] = true;
        while (!q.empty()) {
            cur = q.front().first;
            cnt = q.front().second;
            q.pop();
            if (cur == k) {
                min_cnt = cnt;
                break;
            }
            if (cur * 2 <= SIZE && !visit[cur * 2]) {
                q.push(make_pair(cur * 2, cnt + 1));
                visit[cur * 2= true;
                path[cur * 2= cur;
            }
            if (cur + 1 <= SIZE && !visit[cur + 1]) {
                q.push(make_pair(cur + 1, cnt + 1));
                visit[cur + 1= true;
                path[cur + 1= cur;
            }
            if (cur - 1 >= 0 && !visit[cur - 1]) {
                q.push(make_pair(cur - 1, cnt + 1));
                visit[cur - 1= true;
                path[cur - 1= cur;
            }
        }
        printf("%d\n", min_cnt);
        stack <int> s;
        int temp = k;
        path[n] = n;
        while (temp!=n) {
            int now = temp;
            s.push(now);
            temp = path[temp];
        }
        s.push(n);
        while (!s.empty()) {
            int now = s.top();
            s.pop();
            printf("%d ", now);
        }
        return 0;
    }
    cs

     

    52번~65번까지가 역추적이고, 그 외에는 숨바꼭질1과 동일하다

     

    'BOJ' 카테고리의 다른 글

    [10819] 차이를 최대로  (0) 2021.09.01
    [2174] 로봇 시뮬레이션  (0) 2021.09.01
    [10164] 격자상의 경로  (0) 2021.09.01
    [1495] 기타리스트  (0) 2021.09.01
    [2252] 줄 세우기  (0) 2021.08.31

    댓글