알고리즘/BOJ

[BOJ] 4179 - 불!

서노리 2022. 7. 10. 19:58
반응형

https://www.acmicpc.net/problem/4179

 

4179번: 불!

입력의 첫째 줄에는 공백으로 구분된 두 정수 R과 C가 주어진다. 단, 1 ≤ R, C ≤ 1000 이다. R은 미로 행의 개수, C는 열의 개수이다. 다음 입력으로 R줄동안 각각의 미로 행이 주어진다.  각각의 문

www.acmicpc.net

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

int r, c;
int cnt = 0;
string board[1001];
int board_fire[1001][1001];
int board_path[1001][1001];
int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};
queue<pair<int, int>> path;
queue<pair<int, int>> fire;

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

    cin >> r >> c;

    for(int i = 0; i < r; i++){
        cin >> board[i];
        fill(board_fire[i], board_fire[i] + c, -1);
        fill(board_path[i], board_path[i] + c, -1);
    }

    for(int i = 0; i < r; i++){
        for(int j = 0; j < c; j++){
            if(board[i][j] == 'J'){
                path.push(make_pair(i, j));
                board_path[i][j] = 0;
            }
                
            else if(board[i][j] == 'F'){
                fire.push(make_pair(i, j));
                board_fire[i][j] = 0;
            }
        }
    }

    while(!fire.empty()){
        int x = fire.front().first;
        int y = fire.front().second;
        fire.pop();

        for(int i = 0; i < 4; i++){
            int nx = x + dx[i];
            int ny = y + dy[i];

            if(nx < 0 || nx >= r || ny < 0 || ny >= c){
                continue;
            }

            if(board_fire[nx][ny] >= 0 || board[nx][ny] == '#')
                continue;

            board_fire[nx][ny] = board_fire[x][y] + 1;
            fire.push(make_pair(nx, ny));
        }
    }

    while(!path.empty()){
        int x = path.front().first;
        int y = path.front().second;
        path.pop();

        for(int i = 0; i < 4; i++){
            int nx = x + dx[i];
            int ny = y + dy[i];

            if(nx < 0 || nx >= r || ny < 0 || ny >= c){
                cout << board_path[x][y] + 1;
                return 0;
            }

            if(board_path[nx][ny] >= 0 || board[nx][ny] == '#')
                continue;

            if(board_fire[nx][ny] != -1 && board_fire[nx][ny] <= board_path[x][y] + 1){
                continue;
            }
            board_path[nx][ny] = board_path[x][y] + 1;
            path.push(make_pair(nx, ny));
            
        }
    }
    cout << "IMPOSSIBLE";
}

결과적으로 최단 경로를 구하는 문제이므로 BFS를 이용하지만 응용이 필요한 문제이다.

고려해야할 조건은 다음과 같다.

  • 불이 있는 곳에는 지훈이가 갈 수 없다.
  • 지훈이의 탈출 조건

 

if(board_fire[nx][ny] != -1 && board_fire[nx][ny] <= board_path[x][y] + 1){
	continue;
}

첫 번째 조건을 처리하기 위해서 불이 퍼지는 BFS를 먼저 실행한 후, 지훈이의 BFS를 실행하는데

지훈이가 해당 칸에 도착하는 시간이 해당 칸에 불이 퍼지는 시간과 같거나 작을 경우 갈 수 없다.

 

if(nx < 0 || nx >= r || ny < 0 || ny >= c){
	cout << board_path[x][y] + 1;
	return 0;
}

지훈이는 board의 가장자리에서 탈출가능하므로 이동하려는 칸의 좌표가 board의 크기를 벗어난다면

현재까지의 좌표 + 1을 출력하면서 종료하면 된다.


느낀점

두 가지 종류의 BFS를 각각 실행해주는 문제를 처음 접해서 신기했고 어려웠다.

BFS 자체는 굉장히 형식적이라 쉽다고 생각했는데 다양한 응용 BFS 문제를 풀어보아야겠다.

반응형

'알고리즘 > BOJ' 카테고리의 다른 글

[BOJ] 1062 - 가르침  (0) 2022.08.01
[BOJ] 2580 - 스도쿠  (0) 2022.07.04
[BOJ] 1339 - 단어 수학  (0) 2022.07.01
[BOJ] 2941 - 크로아티아 알파벳  (0) 2022.06.27
[BOJ] 단계별로 풀어보기 - 기본 수학 1  (2) 2022.06.27