https://www.acmicpc.net/problem/13549
dist라는 일차원 배열에 해당 위치에 대한 cost를 저장하고, 현재 위치에 따라 이동 방법을 다르게 해주는 BFS로 정점을 방문하여 문제를 해결하였다. 또한, 가중치가 0인 정점을 더 먼저 방문하기 위해 순간이동을 할 수 있는 경우에는 deque를 이용하여 앞에 넣어주었다.
질문게시판에 올라온 글을 보면 해당 문제는 단순한 BFS를 요구하는 문제가 아니라고한다.
BFS를 하기 위해서는 모든 간선의 가중치가 동일해야 한다는 전제 조건이 필요한데,이 문제는 가중치가 0인 간선 (순간이동) 이 있기 때문에 일반적으로는 단순한 BFS를 쓸 수 없으나, 문제의 특성 때문에 방문 순서에 따라서 단순 BFS로도 우연히도 항상 정답을 찾을 수 있을 뿐이라고한다.
이 문제의 의도대로 알고리즘을 작성하려면 다음 세 가지 방법이 존재한다고 한다.
나는 2번을 방법을 이용해서 풀었다.
#include <iostream>
#include <cstring>
#include <deque>
#include <vector>
using namespace std;
const int MAX = 999999;
int n, k;
int dist[100001];
struct Node {
int current, currentDist;
};
int bfs(int n, int k) {
memset(dist, MAX, sizeof(dist));
deque<Node> q;
q.push_back({n, 0});
while (!q.empty()) {
Node node = q.front();
q.pop_front();
if (node.current == k) {
return dist[k];
}
// 뒤로 한칸 가는게 이득일 때
if (node.current > 0) {
if (dist[node.current - 1] > node.currentDist + 1) {
dist[node.current - 1] = node.currentDist + 1;
q.push_back({node.current - 1, node.currentDist + 1});
}
}
// 앞으로 한칸 가는게 이득일 때
if (node.current < 100000) {
if (dist[node.current + 1] > node.currentDist + 1) {
dist[node.current + 1] = node.currentDist + 1;
q.push_back({node.current + 1, node.currentDist + 1});
}
}
// 점프하는게 이득일 때
if (node.current * 2 <= 100000) {
if (dist[node.current * 2] > node.currentDist) {
dist[node.current * 2] = node.currentDist;
q.push_front({node.current * 2, node.currentDist});
}
}
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
cin >> n >> k;
if (n == k || n * 2 == k) cout << 0;
else if (k < n) cout << n - k;
else cout << bfs(n, k);
return 0;
}