문제 풀이/백준

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

JJJaewon 2024. 3. 4. 17:04
반응형

이 문제는 다익스트라를 이용해서 풀었다.

 

이 문제에서 핵심은 +1, -1, *2를 수행할 때 현재와 목적지와의 관계를 비교하지 않는 것이다.

이는 예제에서 말해주고 있다. 출발지가 5이고, 도착지가 17인데, 10에서 9로 가는 선택이 들어간다.

 

내가 했던 실수는 여기서 현재가 도착지보다 작을 경우, 0이 아니면 *2, +1 을 수행하고, 0이면 +1을 수행하는 식의 로직이 추가되었다는 점이다. 이러면 10에서 9로 가는 로직이 형성되지 않는다.

 

현재와 목적지까지의 상대 위치를 판단하지 않으면 큐에 너무 많은 숫자가 들어오게 되는데, 이를 방지하기 위해 다익스트라 알고리즘을 사용할 수 있다. 다익스트라를 이용하면 항상 현재 비용이 가장 적은 것부터 수행하기 때문에, 정답에 도착했을 때 바로 리턴해도 그것이 정답임을 확신할 수 있다.

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

#define MAX 300000
#define INF 1000000000

int N, K;

struct Compare {
	bool operator() (pair<int, int> &a, pair<int, int> &b) {
		return a.second > b.second;
	}
};

bool inRange(int x) {
	if (0 <= x && x <= MAX) {
		return true;
	}
	return false;
}

int dijkstra(int start, int end) {
	priority_queue<pair<int, int>, vector<pair<int, int>>, Compare> q;
	vector<int> dist(MAX + 1, INF);
	q.push({ start , 0});
	dist[start] = 0;

	while (!q.empty()) {
		int present = q.top().first;
		int presentCost = q.top().second;
		q.pop();

		if (present == end) {
			return presentCost;
		}

		// * 2
		if (inRange(present * 2) && present != 0) {
			int next = present * 2;
			int nextCost = presentCost;

			if (dist[next] > nextCost) {
				dist[next] = nextCost;
				q.push({ next, nextCost });
			}
		}

		// -1
		if (inRange(present - 1)) {
			int next = present - 1;
			int nextCost = presentCost + 1;

			if (dist[next] > nextCost) {
				dist[next] = nextCost;
				q.push({ next, nextCost });
			}
		}

		// + 1
		if (inRange(present + 1)) {
			int next = present + 1;
			int nextCost = presentCost + 1;

			if (dist[next] > nextCost) {
				dist[next] = nextCost;
				q.push({ next, nextCost });
			}
		}
	}

	return -1;
}

int main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	cin >> N >> K;
	int answer = dijkstra(N, K);
	cout << answer << '\n';

	return 0;
}
반응형