BOJ_9376 : 탈옥

2 minute read

문제

상근이는 감옥에서 죄수 두 명을 탈옥시켜야 한다. 이 감옥은 1층짜리 건물이고, 상근이는 방금 평면도를 얻었다.

평면도에는 모든 벽과 문이 나타나있고, 탈옥시켜야 하는 죄수의 위치도 나타나 있다. 감옥은 무인 감옥으로 죄수 두 명이 감옥에 있는 유일한 사람이다.

문은 중앙 제어실에서만 열 수 있다. 상근이는 특별한 기술을 이용해 제어실을 통하지 않고 문을 열려고 한다. 하지만, 문을 열려면 시간이 매우 많이 걸린다. 두 죄수를 탈옥시키기 위해서 열어야 하는 문의 개수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 테스트 케이스의 개수가 주어진다. 테스트 케이스의 수는 100개를 넘지 않는다.

첫째 줄에는 평면도의 높이 h와 너비 w가 주어진다. (2 ≤ h, w ≤ 100) 다음 h개 줄에는 감옥의 평면도 정보가 주어지며, 빈 공간은 ‘.’, 지나갈 수 없는 벽은 ‘*’, 문은 ‘#’, 죄수의 위치는 ‘$’이다.

상근이는 감옥 밖을 자유롭게 이동할 수 있고, 평면도에 표시된 죄수의 수는 항상 두 명이다. 각 죄수와 감옥의 바깥을 연결하는 경로가 항상 존재하는 경우만 입력으로 주어진다.

출력

각 테스트 케이스마다 두 죄수를 탈옥시키기 위해서 열어야 하는 문의 최솟값을 출력한다.

C++ 코드

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <deque>


using namespace std;
int dx[] = { 0, 0, 1, -1 };
int dy[] = { 1, -1, 0, 0 };

vector<vector<int>> bfs(vector<string>& s, int a, int b) {
	int h = s.size();
	int w = s[0].size();
	vector<vector<int>> cage(h, vector<int>(w, -1));
	deque<pair<int, int>> q;
	q.push_back(make_pair(a, b));
	cage[a][b] = 0; // 문을 0개 열었다는 의미

	while (!q.empty()) {
		int x = q.front().first;
		int y = q.front().second;
		q.pop_front();
		//앞에 것부터 pop

		for (int k = 0; k < 4; k++) {
			int nx = x + dx[k];
			int ny = y + dy[k];
			if (nx <0 || nx >= h || ny < 0 || ny >= w) continue;
			if (s[nx][ny] == '*') continue;
			if ((s[nx][ny] == '.' || s[nx][ny] == '$') && cage[nx][ny] == -1) {
				cage[nx][ny] = cage[x][y];
				q.push_front(make_pair(nx, ny));
				// 문을 더이상 열지 않고 갈 수있는 
				// 곳 부터 우선탐색
			}
			else if (s[nx][ny] == '#' && cage[nx][ny] == -1) {
				cage[nx][ny] = cage[x][y] + 1;
				q.push_back(make_pair(nx, ny));
				// 문을 열어야 탐색할 수 있는 곳은
				// 나중에 탐색
			}
		}
	}
	return cage;
}


int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	int t;
	cin >> t;
	while (t--) {
		int h, w;
		cin >> h >> w;
		vector<string> s(h + 2);

		for (int i = 1; i <= h; i++) {
			cin >> s[i];
			s[i] = "." + s[i] + ".";
			//양옆 한칸씩 띄우기
		}
		h += 2;
		w += 2;

		for (int i = 0; i < w; i++) {
			s[0] += ".";
			s[h - 1] += ".";
			//위아래 한칸씩
		}

		vector<vector<int>> cage1 = bfs(s, 0, 0);
		int x1, x2, y1, y2;
		x1 = x2 = y1 = y2 = -1;
		for (int i = 1; i < h; i++) {
			for (int j = 1; j < w; j++) {
				if (s[i][j] == '$') {
					if (x1 == -1) {
						x1 = i;
						y1 = j;
					}
					else {
						x2 = i;
						y2 = j;
					}
				}					
			}
		}
		vector<vector<int>> cage2 = bfs(s, x1, y1);
		vector<vector<int>> cage3 = bfs(s, x2, y2);

		int answer = h * w;
		for (int i = 0; i < h; i++) {
			for (int j = 0; j < w; j++) {
				if (s[i][j] == '*' || cage1[i][j] == -1
					|| cage2[i][j] == -1 || cage3[i][j] == -1) continue;
				int cur = cage1[i][j] + cage2[i][j] + cage3[i][j];
				if (s[i][j] == '#') cur -= 2;
				if (answer > cur) answer = cur;

			}
		}
		cout << answer << '\n';
	}

}

Updated:

Leave a comment