https://www.acmicpc.net/problem/4179
4179번: 불!
입력의 첫째 줄에는 공백으로 구분된 두 정수 R과 C가 주어진다. 단, 1 ≤ R, C ≤ 1000 이다. R은 미로 행의 개수, C는 열의 개수이다. 다음 입력으로 R줄동안 각각의 미로 행이 주어진다. 각각의 문자
www.acmicpc.net
풀이 과정
매 시간 불이 사방으로 번지고 지훈이는 사방으로 한 칸씩 이동할 때 지훈이가 몇 번의 이동만에 탈출 할 수 있는지 구하는 문제이다.
BFS로 지훈의 시간과 불이 번지는 시간을 구한다. 불은 여러 개가 존재 할 수 있으므로 입력시 큐에 넣고 이어서 BFS로 탐색한다. 그리고 지훈이가 테두리에 위치할 경우 바로 탈출이 가능하므로 처음 입력 시 검사가 필요하고, BFS로 지훈이가 불보다 빠를 때만 이동하도록 해서 시간을 구했다.
느낀 점
처음에 설계를 잘못해서 곤혹을 치뤘다. 불이 여러 개 있다는 것을 고려하지 못하고 사람BFS와 불BFS를 하나로 구현하려고 하다보니 생긴 문제였다. 이럴 때는 과감하게 처음부터 다시 설계를 해보는게 필요할 것 같다.
#include<bits/stdc++.h>
using namespace std;
const int MX = 1004, INF = 99999999;
int mp[MX][MX], person[MX][MX], fire[MX][MX];
int n, m, ret;
int my[4] = { 1, 0, -1, 0 }, mx[4] = { 0, 1, 0, -1 };
pair<int, int> sp;
char temp;
queue<pair<int, int>> q;
void input() {
cin >> n >> m;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> temp;
if (temp == '#') mp[i][j] = 1;
else if (temp == '.') mp[i][j] = 0;
else if (temp == 'F')
{
fire[i][j] = 1;
q.push({ i, j });
}
else if (temp == 'J') sp = { i, j };
}
}
return;
}
void output() {
if (ret == 0) cout << "IMPOSSIBLE\n";
else cout << ret << "\n"; //최종 탈출을 위한 ++
return;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
fill(&fire[0][0], &fire[0][0] + MX * MX, INF);
input();
//불 좌표마다 BFS 실행
while (q.size()) {
int fy = q.front().first;
int fx = q.front().second;
q.pop();
for (int v = 0; v < 4; v++) {
int ny = my[v] + fy;
int nx = mx[v] + fx;
if (ny < 0 || ny >= n || nx < 0 || nx >= m || mp[ny][nx]) continue;
if (fire[ny][nx] != INF) continue;
fire[ny][nx] = fire[fy][fx] + 1;
q.push({ ny, nx });
}
}
/*
cout << "\nfire info\n";
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cout << fire[i][j] << " ";
}
cout << "\n";
}
*/
//사람 BFS 실행
person[sp.first][sp.second] = 1;
q.push({ sp.first, sp.second });
while (q.size()) {
int fy = q.front().first;
int fx = q.front().second;
q.pop();
if (fy == n - 1 || fy == 0 || fx == m - 1 || fx == 0) {
//cout << "ans fy fx : " << fy << ", " << fx << "\n";
ret = person[fy][fx];
break;
}
for (int v = 0; v < 4; v++) {
int ny = my[v] + fy;
int nx = mx[v] + fx;
if (ny < 0 || ny >= n || nx < 0 || nx >= m || mp[ny][nx] || person[ny][nx]) continue;
if (fire[ny][nx] <= person[fy][fx] + 1) continue;
//cout << "ny , nx : " << ny << ", " << nx << "\n";
person[ny][nx] = person[fy][fx] + 1;
q.push({ ny, nx });
}
}
/*
cout << "\nperson info\n";
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cout << person[i][j] << " ";
}
cout << "\n";
}
*/
//결과 출력
output();
return 0;
}
'알고리즘 : C++ > BaekJoon' 카테고리의 다른 글
백준 16637번 - 괄호 추가하기 (0) | 2023.06.14 |
---|---|
백준 12869번 - 뮤탈리스크 (0) | 2023.06.13 |
백준 16234번 - 인구 이동 (2회 차) (0) | 2023.06.02 |
백준 2589번 - 보물섬 (2회 차) (0) | 2023.06.02 |
백준 15686번 - 치킨 배달 (2회 차) (0) | 2023.06.01 |