문제 링크는 다음과 같다.

 

https://www.acmicpc.net/problem/1697

 

1697번: 숨바꼭질

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

www.acmicpc.net

 

문제 요약

- 내 위치에서 친구의 위치까지 수직선 위에서 움직이면 된다.

- 움직이는 방법은, 내 위치가 X였다면 1초 이후에 X-1, X+1, 그리고 2*X 이렇게 가능하다.

- 이때 한 번 움직일 때 1초씩 흐른다.

- 나의 위치 X에서 친구의 위치까지 이동하는 데에는 몇 초가 걸릴까?

 

 

위의 상황을 착실하게 구현해주면 된다.

 

먼저 이 문제는 기계적으로 배열 크기를 잡는 모든 이들을 위한 문제라고 할 수 있다.

 

(물론 거기에는 나도 포함되었다)

 

이 문제의 구현 수준은, 절대 24%대의 정답률이 나올만한 것이 아니다.

 

다만 대부분의 사람들이 배열의 크기를 잡을 때 n값의 범위만을 고려했기 때문에 '맞왜틀'을 반복했을 것이다.

 

 

나 또한 초반에는 그렇게 생각했다.

 

1차적으로 이것을 파악할 수 있는 부분은 문제의 힌트에 있다.

 

5에서 17을 가는 길에 18을 거친다. 이것을 보고 내가 만약에 10,0000을 목적지로 잡았다고 하면, 이 위치보다 큰 값을 거쳐서 저 위치로 다다를 가능성도 없지 않다는 것이다.

 

필자의 경우에는, 이 힌트를 보고도 이것을 파악하지 못했고, 몇 가지의 예시를 가지고 print를 찍어보는 방식으로 디버깅을 하던 도중에 깨달았다.

 

 

또, 여러가지의 예시를 넣어보는 과정을 거친 이후에도 해결되지 않는 문제들은 대부분이 극값 혹은 그 근처에서 발생하는 문제였다. 이번 경우에도 그렇다고 볼 수 있다.

 

정확한 배열 크기는 알아내지 못하였고. 그저 배열의 크기를 넉넉하게 잡아주는 방법으로 해결했다.

 

#include<iostream>
#include<queue>
using namespace std;
int n, k;
int vis[300000];
queue<int> q;
int sec = 0;
void bfs(int start) {
	q.push(start);
	vis[start]++;

	while (!q.empty()) {
		int cur = q.front();
		q.pop();
		for (int i = 0; i < 3; i++) {
			int np;
			if (i == 0)
				np = cur - 1;
			else if (i == 1)
				np = cur + 1;
			else
				np = 2 * cur;

			if (np < 0 || np > 100000 || vis[np] >= 0) continue;

			q.push(np);
			vis[np] = vis[cur] + 1;
			if (np == k) return;
		}
	}
}
int main(void) {
	cin >> n >> k;
	for (int i = 0; i < 300000; i++)
		vis[i] = -1;
	bfs(n);
	cout << '\n';
	for (int i = 0; i < 30; i++)
		printf("%d 에서 %d\n", i, vis[i]);
	cout << '\n';
	cout << vis[k] << '\n';
	return 0;
}

+ Recent posts