baekjoon
[백준 ]5427 불
윤만석
2023. 4. 25. 14:22
문제
상근이는 빈 공간과 벽으로 이루어진 건물에 갇혀있다. 건물의 일부에는 불이 났고, 상근이는 출구를 향해 뛰고 있다.
매 초마다, 불은 동서남북 방향으로 인접한 빈 공간으로 퍼져나간다. 벽에는 불이 붙지 않는다. 상근이는 동서남북 인접한 칸으로 이동할 수 있으며, 1초가 걸린다. 상근이는 벽을 통과할 수 없고, 불이 옮겨진 칸 또는 이제 불이 붙으려는 칸으로 이동할 수 없다. 상근이가 있는 칸에 불이 옮겨옴과 동시에 다른 칸으로 이동할 수 있다.
빌딩의 지도가 주어졌을 때, 얼마나 빨리 빌딩을 탈출할 수 있는지 구하는 프로그램을 작성하시오.
입력
첫째 줄에 테스트 케이스의 개수가 주어진다. 테스트 케이스는 최대 100개이다.
각 테스트 케이스의 첫째 줄에는 빌딩 지도의 너비와 높이 w와 h가 주어진다. (1 ≤ w,h ≤ 1000)
다음 h개 줄에는 w개의 문자, 빌딩의 지도가 주어진다.
- '.': 빈 공간
- '#': 벽
- '@': 상근이의 시작 위치
- '*': 불
각 지도에 @의 개수는 하나이다.
출력
각 테스트 케이스마다 빌딩을 탈출하는데 가장 빠른 시간을 출력한다. 빌딩을 탈출할 수 없는 경우에는 "IMPOSSIBLE"을 출력한다.
BFS문제입니다
불이 번지는 상황과 상근이가 탈출하는 상황을 각각 BFS를 사용해주고,
특정 칸에 불이 번지는 최소 시간 t1이라고 하고
상근이가 틍정 칸으로 이동하는 최소시간을 t2라 할때
t1>t2+1이여야 이동할 수 있습니다.
#include<bits/stdc++.h>
#define FAST ios_base::sync_with_stdio(false),cin.tie(NULL);
#define mset(v) memset(v,0,sizeof(v));
#define rep(i,a) for(int i=0;i<a;++i)
#define REP(i,a) for(int i=1;i<=a;++i)
using namespace std;
typedef long long ll;
typedef pair<int, int> pi;
typedef tuple<int, int, int>ti;
typedef vector<int> vi;
typedef vector<vector<int>> vvi;
int dy[] = {-1,0,1,0}, dx[] = {0,1,0,-1}, INF = 987654321;
using namespace std;
int TC, N, M, v[1001][1001], v2[1001][1001];
char mp[1001][1001];
int main() {
FAST;
cin >> TC;
while (TC--) {
cin >> M >> N;
queue<pi>fq;
queue<pi>eq;
vector<pi>out;
mset(mp);
mset(v);
mset(v2);
REP(i, N)REP(j, M) {
cin >> mp[i][j];
if (mp[i][j] == '@') {
v2[i][j] = 1;
eq.push({ i,j });
}
if (mp[i][j] == '*') {
v[i][j] = 1;
fq.push({ i,j });
}
if ((i == 1 || i == N || j == 1 || j == M) && mp[i][j] != '#') {
out.push_back({ i,j });
}
}
while (!fq.empty()) {
auto [y, x] = fq.front();
fq.pop();
rep(i, 4) {
int ny = y + dy[i];
int nx = x + dx[i];
if (ny >= 1 && ny <= N && nx >= 1 && nx <= M && mp[ny][nx] != '#' && !v[ny][nx]) {
v[ny][nx] = v[y][x] + 1;
fq.push({ ny,nx });
}
}
}
while (!eq.empty()) {
auto [y, x] = eq.front();
eq.pop();
rep(i, 4) {
int ny = y + dy[i];
int nx = x + dx[i];
if (ny >= 1 && ny <= N && nx >= 1 && nx <= M && mp[ny][nx] != '#' && (!v[ny][nx] || v[ny][nx]>v2[y][x]+1) && !v2[ny][nx]) {
v2[ny][nx] = v2[y][x] + 1;
eq.push({ ny,nx });
}
}
}
int ans = INT_MAX;
for (auto [y, x] : out) {
if (v2[y][x]) {
ans = min(ans, v2[y][x]);
}
}
ans == INT_MAX ? cout << "IMPOSSIBLE\n" : cout << ans << "\n";
}
}