코딩/백준

[백준]13549번 숨바꼭질3 - C++

최선을 다하는 2022. 11. 1. 16:28

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

 

13549번: 숨바꼭질 3

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

www.acmicpc.net

문제

수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때 걷는다면 1초 후에 X-1 또는 X+1로 이동하게 된다. 순간이동을 하는 경우에는 0초 후에 2*X의 위치로 이동하게 된다.

수빈이와 동생의 위치가 주어졌을 때, 수빈이가 동생을 찾을 수 있는 가장 빠른 시간이 몇 초 후인지 구하는 프로그램을 작성하시오.

입력

첫 번째 줄에 수빈이가 있는 위치 N과 동생이 있는 위치 K가 주어진다. N과 K는 정수이다.

출력

수빈이가 동생을 찾는 가장 빠른 시간을 출력한다.


     두 점 사이의 거리를 구하는 문제이므로 다익스트라 알고리즘을 생각해낼 수 있다. 

 

#include <iostream>
#include <queue>
using namespace std;
#define MAX 100001
typedef pair<int, int> point;

bool vis[100001];
int N, K;

void solve()
{
    priority_queue<point, vector<point>, greater<point> > pq;
    pq.push(make_pair(0, N));
    vis[N] = true;
    while (!pq.empty())
    {
        point top = pq.top();
        pq.pop();
        int cost = top.first;
        int cur = top.second;
        if (cur == K)
        {
            cout << cost;
            break;
        }
        if (cur < 2 * K)
        {
            if (cur * 2 < MAX && !vis[cur * 2])
            {
                vis[cur * 2] = true;
                pq.push(make_pair(cost, cur * 2));
            }
            if (cur - 1 >= 0 && !vis[cur - 1])
            {
                vis[cur - 1] = true;
                pq.push(make_pair(cost + 1, cur - 1));
            }
            if (cur + 1 < MAX && !vis[cur + 1])
            {
                vis[cur + 1] = true;
                pq.push(make_pair(cost + 1, cur + 1));
            }
        }
    }
}
int main()
{
    cin >> N >> K;
    if (N >= K)
         cout << N - K;
    else
        solve();
}

    처음 제출하였을때는 아래의 코드로 정답을 받았다.

#include <iostream>
#include <queue>
using namespace std;
#define INF 987654321;
typedef pair<int, int> point;

int dist[400010];
int N, K;

void solve()
{
    int res = INF;
    priority_queue<point, vector<point>, greater<point> > pq;
    pq.push(make_pair(0, N));
    dist[N] = 0;
    while (!pq.empty())
    {
        point top = pq.top();
        pq.pop();
        int cost = top.first;
        int cur = top.second;
        if (cur == K)
        {
            res = cost;
            break;
        }
        if (cur < 2 * K)
        {
            if(dist[cur - 1] > cost + 1){
                dist[cur - 1] = cost + 1;
                pq.push(make_pair(cost + 1, cur - 1));
            }
            if(dist[cur + 1] > cost + 1){
                dist[cur + 1] = cost + 1;
                pq.push(make_pair(cost + 1, cur + 1));
            }
            if(dist[cur * 2] > cost){
                dist[cur * 2] = cost;
                pq.push(make_pair(cost, cur * 2));
            }
        
        }
    }
    cout << res;
}
int main()
{
    cin >> N >> K;
    for(int i = 0 ; i <= 2* K;i++)
        dist[i] = INF;
    if(N >= K)
        cout << N - K;
    else
        solve();
}

하지만 먼저 처리된 dist가 무조건 작을 것 같아 int 배열이 아닌 bool 배열로 전환할 수 있어서 바꾸려 하였다. 바꾸었더니 정답 처리가 되지 않아 생각을 해본 결과 -1 +1 *2의 순서로 조건문을 작성한 경우 1의 경우 +1과 *2의 경우 모두 2가 되지만 cost는 +1의 경우가 더 높게 된다. int 배열의 경우 cost 가 *2 가 더 낮아 최신화가 되지만 bool 배열의 경우 +1의 경우에서 vis 가 true가 되어 *2에서 처리되지 못하여 틀리게 되었던 것이다. cost 가 낮은 *2를 먼저 계산해야 최신화할 수 있다.

 

'코딩 > 백준' 카테고리의 다른 글

[백준]1261번 알고스팟 - C++  (0) 2022.11.03
[백준]1504번 특정최단경로 - C++  (0) 2022.11.02
[백준] 1967번 트리의 지름 - C++  (2) 2022.10.05
[백준] 1753번 최단경로 - C++  (0) 2022.10.04
[백준]7576번 토마토 - C/C++  (0) 2022.10.02