전공/알고리즘
백준 1697(숨바꼭질)
xkdlaldfjtnl
2020. 6. 17. 13:57
https://www.acmicpc.net/problem/1697
1697번: 숨바꼭질
문제 수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가
www.acmicpc.net
조건들을 추가해서 더 쉽게 접근할 수 있을까. 고민을 해보았지만, 반례들이 존재했다. 그래서 그냥 bfs로 완전탐색을 하였다. dfs대신 bfs를 선택한 이유는 이 문제는 전형적인 턴제의 문제여서이다. 그리고 만약에 dfs로 접근을 한다면, 멈출 조건을 설정하는 것이 너무 까다롭게 된다.
그래서 턴제의 bfs를 선택하였다.
*2 , +1, -1 을 계속해서 한 뒤에 몇 번을 해야지 최소가 나올까 인데, 만약에 bfs로 한다면 모든 경우에 대해서 구한 뒤 그 중 최솟값을 결정하는게 아니라 무조건 최소의 경우가 결괏값으로 한번에 저장이 된다.
그리고, 배열 index 범위초과 접근에 대해서 주의하자. 범위를 벗어나게 된다면 런타임 에러가 발생한다.
만약 if(v[index-1] > 0 && index > 0) 이런 조건문이 있다고 한다면, v[index-1] > 0 에 대해서 조사를 한 뒤에 그 다음 조건에 대해서 확인을 하기 때문에, index>0조건을 먼저 넣는 것이 중요하다.
그리고 대부분의 그래프 문제와 같이 visited를 잘 사용하는 것이 중요하다.
#include<iostream>
#include<queue>
using namespace std;
#define MAX 100002
int N, K, cnt=1, tmp;
bool visited[MAX] = { false };
bool answer = false;
queue<int> q;
queue<int> q2;
void bfs() {
while (1) {
while (!q.empty()) {
tmp = q.front();
q.pop();
if (tmp<MAX && !visited[tmp + 1]) {
q2.push(tmp + 1);
visited[tmp + 1] = true;
if ((tmp + 1) == K) answer = true;
}
if (tmp>0 && !visited[tmp - 1]) {
q2.push(tmp - 1);
visited[tmp - 1] = true;
if ((tmp - 1) == K) answer = true;
}
if (2*tmp <= MAX && !visited[2 * tmp]) {
q2.push(2 * tmp);
visited[2 * tmp] = true;
if ((2 * tmp) == K) answer = true;
}
if (answer) {
cout << cnt << "\n";
return;
}
if (q.empty()) cnt++;
}
while (!q2.empty()) {
tmp = q2.front();
q2.pop();
if (tmp < MAX && !visited[tmp + 1]) {
q.push(tmp + 1);
visited[tmp + 1] = true;
if ((tmp + 1) == K) answer = true;
}
if (tmp > 0 && !visited[tmp - 1]) {
q.push(tmp - 1);
visited[tmp - 1] = true;
if ((tmp - 1) == K) answer = true;
}
if (2*tmp <= MAX && !visited[2 * tmp]) {
q.push(2 * tmp);
visited[2 * tmp] = true;
if ((2 * tmp) == K) answer = true;
}
if (answer) {
cout << cnt << "\n";
return;
}
if (q2.empty()) cnt++;
}
}
}
int main() {
cin >> N >> K;
if (N == K) {
cout << 0 << "\n";
return 0;
}
q.push(N);
visited[N] = true;
bfs();
}