Notice
Recent Posts
Recent Comments
Link
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
Archives
Today
Total
관리 메뉴

hwooo

BOJ (C/C++) 13549번: 숨바꼭질 3 본문

Study/Algorithm

BOJ (C/C++) 13549번: 숨바꼭질 3

hwooo 2022. 12. 8. 03:16


풀이

BFS로 탐색하되, *2 이동은 0이므로 그 부분만 따로 계산해줌.

방문한 노드에는 현재 노드에 도착할 때까지 걸리는 시간을 저장해주고, 다음에 방문할 때 저장된 값보다 걸린 시간이 적은 경우에만 값을 갱신, 계산하도록 했다.

 

알고리즘이 다익스트라로 구분되었기에 우선순위 큐도 써보았는데 정렬이 필요해서인지 시간도 메모리도 더 컸다.


코드 1 - 큐

#include <stdio.h>
#include <queue>
#include <algorithm>
using namespace std;
int visited[100001];
int Find(int start, int end) {
	// 시작지점이 종료지점과 같다면 0 반환
	if (start == end) return 0;

	int now, sec, d[3] = { -1,1 }, min = 10000000;
	queue <pair<int, int>> Q;

	// init
	Q.push({ start, 0 });
	visited[start] = 0;
	fill(visited, visited + 100001, min); // 최댓값으로 설정

	while (!Q.empty()) {
		now = Q.front().first, sec = Q.front().second;
		Q.pop();

		d[2] = now; // 3번째는 *2 이동

		for (int i = 0; i < 3; i++) {
			int next = now + d[i];

			// 방문할 위치의 시간이 현재 방문할 때 걸리는 시간보다 적을 경우 방문할 필요 없음
			// 이 줄 없어도 돌아가는 시간은 차이 없긴 한데 그래도 있는 게 시간을 좀 더 줄일 수는 있을 것 같음
			if (next < 0 || next > 100000 || visited[next] <= sec) continue;

			if (next == end) {
				if (i != 2) min = min < sec + 1 ? min : sec + 1;
				else min = min < sec ? min : sec;
				visited[next] = min;
			}
			else {
				if (i != 2) {
					// 다음 방문할 노드까지 걸리는 시간이 min보다 크다면 큐에 저장 X
					if (sec + 1 < min) Q.push({ next, sec + 1 });
					visited[next] = sec + 1;
				}
				else {
					Q.push({ next, sec });
					visited[next] = sec;
				}
			}
		}
	}
	return min;
}
int main() {
	int N, K;
	scanf("%d %d", &N, &K);
	printf("%d", Find(N, K));
	return 0;
}

코드 2  -우선순위 큐

 

#include <stdio.h>
#include <queue>
#include <algorithm>
using namespace std;
int visited[100001];
int Find(int start, int end) {
	// 시작지점이 종료지점과 같다면 0 반환
	if (start == end) return 0;

	int now, sec, d[3] = { -1,1 }, min = 10000000;
	priority_queue <pair<int, int>, vector <pair<int, int>>, greater<pair<int, int>>> Q;

	// init
	Q.push({ 0,start }); visited[start] = 0;
	fill(visited, visited + 100001, min);	// 최댓값으로 설정


	while (!Q.empty()) {
		now = Q.top().second, sec = Q.top().first;
		Q.pop();

		// 우선순위 큐이므로 sec가 큰 게 한 번 나온 이후로는 모든 sec > min
		// 코드 1과 이 부분만 다름
		if (sec >= min) break;

		d[2] = now; // 3번째는 *2 이동

		for (int i = 0; i < 3; i++) {
			int next = now + d[i];

			// 방문할 위치의 시간이 현재 방문할 때 걸리는 시간보다 적을 경우 방문할 필요 없음
			if (next < 0 || next > 100000 || visited[next] <= sec) continue;

			if (next == end) {
				if (i != 2) min = min < sec + 1 ? min : sec + 1;
				else min = min < sec ? min : sec;
				visited[next] = min;
			}
			else {
				if (i != 2) {
					// 다음 방문할 노드까지 걸리는 시간이 min보다 크다면 큐에 저장 X
					if (sec + 1 < min) Q.push({ sec + 1, next });
					visited[next] = sec + 1;
				}
				else {
					Q.push({ sec, next });
					visited[next] = sec;
				}
			}
		}
	}
	return min;
}
int main() {
	int N, K;
	scanf("%d %d", &N, &K);
	printf("%d", Find(N, K));
	return 0;
}