[백준] 숨바꼭질_1697번

[백준] 숨바꼭질

문제


링크 : BOJ

수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때 걷는다면 1초 후에 X-1 또는 X+1로 이동하게 된다. 순간이동을 하는 경우에는 1초 후에 2*X의 위치로 이동하게 된다.

수빈이와 동생의 위치가 주어졌을 때, 수빈이가 동생을 찾을 수 있는 가장 빠른 시간이 몇 초 후인지 구하는 프로그램을 작성하시오.





풀이


수빈이가 동생을 찾을 때 시간 당 갈 수 있는 방법의 수는 3가지이다. 이 3가지를 구현하고 3가지 중 하나라도 이행했을 때, 시간이 1 증가하게 된다. 따라서 {행동, 시간} 순으로 쌍을 이뤄 q에 저장한다.

그리고 각 행동마다 시간이 달라지므로 너비 우선 탐색을 해서 중복해서 방문했던 경우와 범위 밖으로 갔을 경우는 포함시키지 않는다.

결과는 다음과 같다.

#include <iostream>
#include <queue>
using namespace std;
int N, K;
int t = 0;
bool visit[100001] = { false };

queue<pair<int, int>> q;
int bfs()
{
	visit[q.front().first] = true;
	while (!q.empty())
	{
		int p = q.front().first + 1;
		int m = q.front().first - 1;
		int x = q.front().first * 2;
		int t = q.front().second + 1;
		if (p == K || m == K || x == K)
		{
			return t;	
		}
		q.pop();

		if (x < 100001 && !visit[x])
		{
			q.push({ x, t });
			visit[x] = true;
		}

		if ( p < 100001 && !visit[p])
		{
			q.push({ p,t });
			visit[p] = true;
		}

		if (m >= 0 && !visit[m])
		{
			q.push({ m, t });
			visit[m] = true;
		}
	}
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie();


	cin >> N >> K;
	if (N == K)
	{
		cout << 0 << endl;
		return 0;
	}
	q.push({ N, t });
	cout << bfs() ;
	return 0;
}




실수했던 점


계속 런타임 오류가 떴었는 데, 그 이유를 찾지 못해 고생했었다. 그 이유는 보통 범위 바깥에 있는 배열을 지정하면서 검사를 했기 때문이다.

범위 바깥에 있을 경우 예외를 시켜줬긴 했는데, 그 전에 배열에서 먼저 확인을 해버리면 버그가 뜨게 된다.

 if (x < 100001 && !visit[x])
 if ( p < 100001 && !visit[p])
 if (m >= 0 && !visit[m])

이 부분에서 visit배열의 위치를 앞으로 했더니 이미 확인을 하고 있는 상태이기 때문에 런타임 오류가 뜨게 된 것이었다… 배열을 사용할 땐, 이 부분을 조심해서 쓰자.