[C++] 백준 1194: 달이 차오른다, 가자.

Cyan·2024년 2월 25일
0

코딩 테스트

목록 보기
84/166

백준 1194: 달이 차오른다, 가자.

문제 요약

민식이가 미로를 탈출하는데 걸리는 이동 횟수의 최솟값을 구하는 프로그램을 작성하시오. 미로는 빈 칸과 벽, 열쇠, 문, 현재 위치, 출구 위치가 주어진다. 문을 지나가기 위해서는 그에 대응하는 열쇠가 필요하다.

문제 분류

  • 그래프 이론
  • 그래프 탐색
  • BFS
  • 비트마스킹

문제 풀이

BFS로 탐색하는 문제인데, 열쇠의 소지 유무가 들어간 문제이다. 왔던 경로를 탐색하더라도 소지한 열쇠가 다르다면 아예 다른 경로로 파악해야 하므로 visited배열은 key가 들어간 3차원 배열이어야 할 것이다.

기본적인 BFS에서 소지한 키의 유무를 비트마스킹으로 표현한 변수가 더 필요하다. 즉, 현재 소지한 키의 변수를 key라고 한다면, key |= 1 << (ary[nexty][nextx] - 'a')의 식이 될 것이다. 이렇게 하면, ary[nexty][nextx]를 탐색할 때 해당 값이 a~f일 때, a1번 비트를, b2번 비트를... 이런식으로 f6번 비트를 1로 만들 것이다.

key를 갱신하여 탐색하는 부분에서 잘못한다면, 시간초과가 난다. 현재 갖고있는 키를 먼저 갱신을 하고, visited배열을 검사한 뒤, 큐에 넣어주면 된다.

풀이 코드

#include <stdio.h>
#include <iostream>
#include <queue>

using namespace std;

bool visited[50][50][1 << 6];
short dir[4][2] = { {0,1}, {0,-1}, {1,0},{-1,0} };

int main()
{
	queue<pair<pair<int, int>,int>> q;
	short n, m, x, y, key, qsize, level = -1;
	char ary[50][50];
	bool sol = false;
	cin >> n >> m;
	getchar();
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			scanf("%c", &ary[i][j]);
			if (ary[i][j] == '0') {
				x = j;
				y = i;
			}
		}
		getchar();
	}
	q.push({ {x, y}, 0 });
	while (!q.empty()) {
		qsize = q.size();
		level++;
		while (qsize--) {
			x = q.front().first.first;
			y = q.front().first.second;
			key = q.front().second;
			visited[y][x][key] = true;
			q.pop();
			if (ary[y][x] == '1') {
				sol = true;
				break;
			}
			for (int i = 0; i < 4; i++) {
				int nextx = x + dir[i][1];
				int nexty = y + dir[i][0];

				if (nextx >= 0 && nextx < m && nexty >= 0 && nexty < n) {
					int nextkey = key;
					if (ary[nexty][nextx] == '#') continue;
					if (ary[nexty][nextx] >= 'a' && ary[nexty][nextx] <= 'f')
						nextkey |= 1 << (ary[nexty][nextx] - 'a');
					else if (ary[nexty][nextx] >= 'A' && ary[nexty][nextx] <= 'F') {
						if (!(key & (1 << (ary[nexty][nextx] - 'A')))) continue;
					}
					if (!visited[nexty][nextx][nextkey]) {
						visited[nexty][nextx][nextkey] = true;
						q.push({ {nextx, nexty}, nextkey });
					}
				}
			}
		}
		if (sol) break;
	}
	if (sol) cout << level;
	else cout << -1;
	return 0;
}

0개의 댓글