백준 13549 - 숨바꼭질3

1 minute read

문제링크

문제설명

  • 수빈이는 현재 점 N(0 ~ 100,000)에 있고, 동생은 점 K(0 ~ 100,000)에 있다.
  • 수빈이는 걷거나 순간이동을 할 수 있다. 수빈이 위치가 X일 때, 다음과 같이 3가지 이동 방법이 있다.
    • X -> X+1 (1초 소모)
    • X -> X-1 (1초 소모)
    • X -> 2*X (0초 소모)
  • 수빈이와 동생의 위치가 주어졌을 때, 수빈이가 동생을 찾을 수 있는 가장 빠른 시간이 몇 초후인지 구하라

문제접근

  • 시작지점(N)이 정해져 있고, 간선의 가중치가 0, -1, 1 로 세가지가 존재하므로 다익스트라 알고리즘을 사용하면 된다.
  • time[idx] 는 idx번 위치로 이동할 때까지 걸린 시간이 담긴다. 다익스트라 알고리즘을 위해 초기값은 INF 로 설정한다.
  • 이동방법은 3가지가 존재하므로, 각 3가지에 대해서 time[idx] 에 담긴 소요시간과 현재 위치에서 다음 위치로 이동할 때 걸리는 누적된 소요시간을 비교한다.
  • n >= k 인 경우에는 수빈이가 동생에게 가기 위한 방법은 X->X-1 방법 밖에 없음에 유의한다.

구현

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;

#define MAX 100000
#define INF 100000

int n, k;
// 최소힙 (first 기준으로 오름차순 정렬)
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
vector<int> time(MAX + 1, INF);

bool isValid(int x) {
	if (x<0 || x>MAX) return false;
	else return true;
}

void dijkstra() {
	time[n] = 0;
	pq.push(make_pair(0, n));
	
	while (!pq.empty()) {
		pair<int, int> cnode = pq.top();
		pq.pop();

		if (time[cnode.second] < cnode.first) continue;
		 
		// 뒤로 한칸 가는 경우
		int nextPos1 = cnode.second - 1;
		if (isValid(nextPos1) && (time[nextPos1] > cnode.first + 1)) {
			time[nextPos1] = cnode.first + 1;
			pq.push(make_pair(cnode.first + 1, nextPos1));
		}

		// 앞으로 한칸 가는 경우
		int nextPos2 = cnode.second + 1;
		if (isValid(nextPos2) && (time[nextPos2] > cnode.first + 1)) {
			time[nextPos2] = cnode.first + 1;
			pq.push(make_pair(cnode.first + 1, nextPos2));
		}

		// 순간이동
		int nextPos3 = cnode.second * 2;
		if (isValid(nextPos3) && (time[nextPos3] > cnode.first)) {
			time[nextPos3] = cnode.first;
			pq.push(make_pair(cnode.first, nextPos3));
		}
	}
}

int main()
{
	cin.tie(NULL);
	ios_base::sync_with_stdio(false);
	scanf("%d %d", &n, &k);

	int minDist = 0;
	if (n >= k) minDist = n - k;
	else {
		dijkstra();
		minDist = time[k];
	}

	printf("%d\n", minDist);
	return 0;
}

Leave a comment