https://www.acmicpc.net/problem/5427
5427번: 불
상근이는 빈 공간과 벽으로 이루어진 건물에 갇혀있다. 건물의 일부에는 불이 났고, 상근이는 출구를 향해 뛰고 있다. 매 초마다, 불은 동서남북 방향으로 인접한 빈 공간으로 퍼져나간다. 벽에
www.acmicpc.net
2차원 BFS문제다.
불의 경우를 먼저 탐색하고 상근의 경우를 탐색한후 거리를 비교해서 판단한다.
구현 방법
- '*' 좌표에서 탐색을 시작하기 위해 해당 좌표를 큐(QF)에 넣음.
- '@' 좌표에서 탐색을 시작하기 위해 해당 좌표를 큐(QS)에 넣음
- 큐(QF)에서 원소를 꺼내 우측, 좌측, 전방, 후방, 위, 아래 인접한 칸에 대해 4번 탐색함.
- 해당 칸이 범위 밖인경우, 방문했거나(거리가 0 이상) 벽인경우('#') 건너뜀.
- 큐가 빌때까지 반복.
- 큐(QS)에서 원소를 꺼내 우측, 좌측, 전방, 후방, 위, 아래 인접한 칸에 대해 4번 탐색함.
- 다음 칸이 범위 밖(탈출 성공)인 경우 현재 좌표까지의 거리를 출력하고 break.
- 다음 칸이 벽이거나 방문했을경우 건너뜀.
- 다음 칸이 불이 지나가고 상근이가 간 거리보다 작거나 같은경우 넘어감.
- 큐가 빌때까지 반복하고 큐가 비었음에도 탈출하지 못했다면 Trapped 출력.
코드로 살펴보자.
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <stack>
#include <queue>
#include <tuple>
#include <cstring>
using namespace std;
// 탐색 방향
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
// 입력 받을 맵
char board[1002][1002];
// 상근의 거리
int distS[1010][1010];
// 불의 거리
int distF[1010][1010];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int t;
cin >> t;
while (t--) {
int w, h;
cin >> w >> h;
// 불의 큐
queue<pair<int, int>> QF;
// 상근의 큐
queue<pair<int, int>> QS;
bool isEscape = false;
// dist 모두 -1로 초기화
for (int i = 0; i < h; i++) {
fill(distF[i], distF[i] + w, -1);
fill(distS[i], distS[i] + w, -1);
}
// 입력
for(int i = 0; i < h; i++)
for (int j = 0; j < w; j++) {
cin >> board[i][j];
// 불의 좌표를 큐에 넣고 dist 0으로 초기화
if (board[i][j] == '*') {
QF.push({ i,j });
distF[i][j] = 0;
}
// 상근의 좌표를 큐에 넣고 dist 0으로 초기화
if (board[i][j] == '@') {
QS.push({ i,j });
distS[i][j] = 0;
}
}
// 불의 경우 먼저
while (!QF.empty())
{
pair <int, int> cur = QF.front();
QF.pop();
// 좌우전후 4방향 탐색
for (int dir = 0; dir < 4; dir++) {
int nx = cur.first + dx[dir];
int ny = cur.second + dy[dir];
// 범위를 벗어나는 경우 넘어감
if (nx < 0 || nx >= h || ny < 0 || ny >= w) continue;
// 이미 방문했거나, 벽인경우 넘어감
if (distF[nx][ny] >= 0 || board[nx][ny] == '#') continue;
distF[nx][ny] = distF[cur.first][cur.second] + 1;
QF.push({ nx, ny });
}
}
// 상근의 경우
while (!QS.empty())
{
pair <int, int> cur = QS.front();
QS.pop();
for (int dir = 0; dir < 4; dir++) {
int nx = cur.first + dx[dir];
int ny = cur.second + dy[dir];
// 범위를 벗어남 : 탈출
if (nx < 0 || nx >= h || ny < 0 || ny >= w) {
isEscape = true;
cout << distS[cur.first][cur.second] + 1 << '\n';
break;
}
if (distS[nx][ny] >= 0 || board[nx][ny] == '#') continue;
//
if (distF[nx][ny] != -1 && distS[cur.first][cur.second] + 1 >= distF[nx][ny]) continue;
distS[nx][ny] = distS[cur.first][cur.second] + 1;
QS.push({ nx, ny });
}
// 위의 for문이 남았을 경우 while문을 나가는 break를 추가해줘야함.
if (isEscape)
break;
}
if (!isEscape)
cout << "IMPOSSIBLE" << '\n';
}
return 0;
}
'자료구조 & 알고리즘 > 백준' 카테고리의 다른 글
백준 2206 C++ (BFS) (2) | 2024.01.25 |
---|---|
백준 13913 C++ (BFS) (0) | 2024.01.18 |
백준 6593 C++ (BFS) (0) | 2024.01.16 |
백준 9251 C++ (DP) (2) | 2024.01.14 |
백준 1915 C++ (DP) (0) | 2024.01.11 |