득이공간

[백준 C++] 12851 숨바꼭질 2 - 너비우선탐색 본문

PS/알고리즘 문제풀이

[백준 C++] 12851 숨바꼭질 2 - 너비우선탐색

쟁득 2024. 3. 12. 12:01
 

12851번: 숨바꼭질 2

수빈이는 동생과 숨바꼭질을 하고 있다. 수빈이는 현재 점 N(0 ≤ N ≤ 100,000)에 있고, 동생은 점 K(0 ≤ K ≤ 100,000)에 있다. 수빈이는 걷거나 순간이동을 할 수 있다. 만약, 수빈이의 위치가 X일 때

www.acmicpc.net

#include <iostream>
#include <queue>
using namespace std;

int Time[100001];
int Count[100001];
bool Visited[100001];
queue<int> SQ;

void NeighborCheck(int Neighbor, int Current)
{
	if (Neighbor < 0 || Neighbor > 100000)
	{
		return;
	}

	int CurTime = Time[Neighbor];
	int NewTime = Time[Current] + 1;
	if (NewTime < CurTime)
	{
		Time[Neighbor] = NewTime;
		Count[Neighbor] = Count[Current];
	}
	else if (NewTime == CurTime)
	{
		Count[Neighbor] += Count[Current];
	}

	SQ.emplace(Neighbor);
}

void BFS(int Start, int End)
{
	Time[Start] = 0;
	Count[Start] = 1;
	SQ.emplace(Start);
	while (!SQ.empty())
	{
		int Current = SQ.front();
		SQ.pop();

		if (Visited[Current])
		{
			continue;
		}

		Visited[Current] = true;
		NeighborCheck(Current - 1, Current);
		NeighborCheck(Current + 1, Current);
		NeighborCheck(2 * Current, Current);
	}
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr); cout.tie(nullptr);

	for (int i = 0; i <= 100000; ++i)
	{
		Time[i] = 1000000;
	}

	int N, K;
	cin >> N >> K;

	if (N != K)
	{
		BFS(N, K);
	}
	else
	{
		Time[K] = 0;
		Count[K] = 1;
	}

	cout << Time[K] << '\n';
	cout << Count[K];
}

 

일반적인 BFS 문제들보다 조건이 까다로운 문제입니다.

문제 풀이 시 중요한 부분은 다음과 같습니다.

 

1. 각 노드로 향하는 최단경로의 개수를 저장하는 Count 배열 관리

1-a. 해당 노드에 도착했을 때, 최단경로가 갱신되면 이전 노드의 Count 개수를 전달 받는다.

1-b. 해당 노드에 도착했을 때, 최단경로와 같은 길이로 도착했다면 이미 저장된 Count 값에 이전 노드의 Count 개수를 더해준다.

2. 인접 노드 확인할 때 이미 방문했던 노드도 확인 (모든 경로의 경우를 확인해봐야 하기 때문)