서의 공간

[백준] 4179_불! 본문

Algorithm/백준

[백준] 4179_불!

홍서의 2020. 12. 3. 17:42

[문제]: 4179번: 불! (acmicpc.net)

 

불의 이동은 지훈이의 이동에 독립적이다. 지훈이가 어떻게 움직이든 불은 확산되는 규칙에 따라 계속 확산시켜나가면 된다. 반면 지훈이는 그렇지 않다. 지훈이는 불의 이동에 따라 움직임에 제한을 받게 된다. 이렇게 두 시작점이 서로 간에 영향을 주지 않는 경우라면(현재 불만 지훈이의 이동에 영향을 준다), 두 번의 BFS만으로 해결할 수 있다. 불만 먼저 BFS을 하여 각 공간의 시간들을 구한 후, 지훈이를 BFS 한다. 지훈이가 각 장소에 도착하는 시간과 불이 도착하는 시간을 비교하여 움직임을 제한한다. 추가적인 내용은 코드에 주석으로 달아놓았다.

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

string board[1001];
int dist1[1001][1001]; // 불의 전파 시간
int dist2[1001][1001]; // 지훈이의 이동 시간
int dx[4] = { 1, 0, -1, 0 };
int dy[4] = { 0, -1, 0, 1 };
int R, C;

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

	cin >> R >> C;
	for (int i = 0; i < R; ++i) {
		fill(dist1[i], dist1[i] + C, -1);
		fill(dist2[i], dist2[i] + C, -1);
	}

	for (int i = 0; i < R; ++i)
		cin >> board[i];
	
	queue<pair<int, int>> q1;
	queue<pair<int, int>> q2;
	for (int i = 0; i < R; ++i) {
		for (int j = 0; j < C; ++j) {
			if (board[i][j] == 'F') {
				q1.push({ i, j });
				dist1[i][j] = 0;	// 시작 거리 0
			}
			if (board[i][j] == 'J') {
				q2.push({ i, j });
				dist2[i][j] = 0;	// 시작 거리 0
			}
		}
	}

	// 불에 대한 BFS
	while (!q1.empty()) {
		auto cur = q1.front(); q1.pop();
		for (int dir = 0; dir < 4; ++dir) {
			int nx = cur.first + dx[dir];
			int ny = cur.second + dy[dir];
			if (nx < 0 || nx >= R || ny < 0 || ny >= C) continue;
			if (dist1[nx][ny] >= 0 || board[nx][ny] == '#') continue;
			dist1[nx][ny] = dist1[cur.first][cur.second] + 1;
			q1.push({ nx, ny });
		}
	}

	// 지훈이에 대한 BFS
	while (!q2.empty()) {
		auto cur = q2.front(); q2.pop();
		for (int dir = 0; dir < 4; ++dir) {
			int nx = cur.first + dx[dir];
			int ny = cur.second + dy[dir];
			// 가장자리에 닿아 벗어났기 때문에 성공
			if (nx < 0 || nx >= R || ny < 0 || ny >= C) {
				cout << dist2[cur.first][cur.second] + 1;
				system("pause");
				return 0;
			}
			if (dist2[nx][ny] >= 0 || board[nx][ny] == '#') continue;
			// 불이 지나간 곳이고
			// 불이 지나갔을 때 시간과 지훈이가 지나갔을 때 시간을 비교했을 때
			// 지훈이가 더 크거나 같다는 것은 불이랑 동시에 도착하거나 이미 늦었다는 것이므로
			// 지훈이는 그쪽을 못감. 따라서 그냥 continue
			if (dist1[nx][ny] != -1 && dist1[nx][ny] <= dist2[cur.first][cur.second] + 1) continue;
			// 모든 if 조건을 통과한 경우는 빈 공간이면서, 불이 더 늦는 곳임
			// 즉 지훈이가 지나갈 수 있는 공간이다
			dist2[nx][ny] = dist2[cur.first][cur.second] + 1;
			q2.push({ nx, ny });
		}
	}
	// 지훈이의 BFS가 끝나버리면 결코 가장자리에 못닿았다는 뜻이므로 불가능
	cout << "IMPOSSIBLE" << '\n';
	system("pause");
	return 0;
}

'Algorithm > 백준' 카테고리의 다른 글

[백준] 1629_곱셈  (0) 2020.12.11
[백준] 1697_숨바꼭질  (0) 2020.12.03
[백준] 7576_토마토  (0) 2020.12.03
[백준] 1926_그림  (0) 2020.12.03
[백준] 1676_팩토리얼 0의 개수  (0) 2020.11.30
Comments