baekjoon
[백준] 13549 숨바꼭질 3 - 0-1 BFS
윤만석
2023. 3. 27. 13:14
문제
수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때 걷는다면 1초 후에 X-1 또는 X+1로 이동하게 된다. 순간이동을 하는 경우에는 0초 후에 2*X의 위치로 이동하게 된다.
수빈이와 동생의 위치가 주어졌을 때, 수빈이가 동생을 찾을 수 있는 가장 빠른 시간이 몇 초 후인지 구하는 프로그램을 작성하시오.
입력
첫 번째 줄에 수빈이가 있는 위치 N과 동생이 있는 위치 K가 주어진다. N과 K는 정수이다.
출력
수빈이가 동생을 찾는 가장 빠른 시간을 출력한다.
#include<bits/stdc++.h>
#define FAST ios_base::sync_with_stdio(false);cin.tie(NULL)
#define mset(v) memset(v,0,sizeof(v));
#define rep(i,a) for(int i=0;i<a;++i)
#define REP(i,a) for(int i=1;i<=a;++i)
using namespace std;
typedef long long ll;
typedef pair<int, int> pi;
typedef tuple<int, int, int>ti;
typedef vector<int> vi;
typedef vector<vector<int>> vvi;
int dy[] = { -1,0,1,0 }, dx[] = { 0,1,0,-1 };
int N, K,d[200001];
int main() {
FAST;
memset(d,0x3f,sizeof(d));
deque<int>dq;
cin >> N >> K;
dq.push_back(N);
d[N] = 0;
while (!dq.empty()) {
auto f = dq.front();
dq.pop_front();
if (f == K) {
cout << d[f];
break;
}
int doub = f * 2;
if (doub != N && doub <= 200000 && d[doub] > d[f] + 1) {
d[doub] = d[f];
dq.push_front(doub);
}
int le = f - 1, ri = f + 1;
if (le >= 0 && d[le] > d[f] + 1) {
d[le] = d[f] + 1;
dq.push_back(le);
}
if (ri <= 200000 && d[ri] > d[f] + 1) {
d[ri] = d[f] + 1;
dq.push_back(ri);
}
}
}
0-1 BFS 알고리즘은 평범한 bfs에 간선의 가중치가 1or0일 때 사용할 수 있는 기법입니다.
큐를 사용하는 일반적인 BFS와 달리,
0-1 BFS는 덱큐를 사용합니다.
덱큐는 앞과 뒤로 데이터를 넣고 뺄 수 있습니다.
간선의 가중치가 1인경우, 덱큐의 맨 앞에 데이터를 넣습니다.
간선의 가중치가 0인경우, 덱큐의 맨 뒤에 데이터를 넣습니다.
0초 뒤에 2*X만큼 이동할 수 있기 때문에, 각 정점에서 2배만큼의 거리를 움직이는 간선은 가중치가 1이고,
앞뒤로 한칸씩 움직일 때눈 간선의 가중치가 0입니다.
다익스트라 알고리즘과 마찬가지로,
[다음 노드까지 이동거리] > [현재 노드까지 이동거리] + [현재노드에서 다음노드까지 거리] 인 경우,
다음노드까지 거리를 갱신합니다.