[BOJ / C++] 불 (BFS)

2025. 7. 13. 14:38·코딩테스트/BOJ

문제링크: https://www.acmicpc.net/problem/5427

 

1. 코드

#include <bits/stdc++.h>
using namespace std;

int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};

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

    int n;
    cin >> n;
    while (n--) {
        int c, r;
        cin >> c >> r;

        queue<pair<int, int>> fireQ;
        queue<pair<int, int>> personQ;
        
        vector<vector<int>> fDist(r, vector<int>(c, -1));
        vector<vector<int>> pDist(r, vector<int>(c, -1));
        
        vector<vector<char>> board(r, vector<char>(c, ' '));
        for (int i = 0; i < r; i++) {
            string str;
            cin >> str;
            for (int j = 0; j < c; j++) {
                board[i][j] = str[j];
                
                if (board[i][j] == '*') {
                    fireQ.push({i, j});
                    fDist[i][j] = 0;
                }
                else if (board[i][j] == '@') {
                    personQ.push({i, j});
                    pDist[i][j] = 0;
                }
            }
        }

        // fire bfs
        while (!fireQ.empty()) {
            auto cur = fireQ.front(); fireQ.pop();
            int x = cur.first;
            int y = cur.second;
            
            for (int dir = 0; dir < 4; dir++) {
                int nx = x + dx[dir];
                int ny = y + dy[dir];
                if (nx < 0 || nx >= r || ny < 0 || ny >= c) continue;
                if (board[nx][ny] == '#' || fDist[nx][ny] >= 0) continue;
                
                fireQ.push({nx, ny});
                fDist[nx][ny] = fDist[x][y] + 1;
            }
        }

        // person bfs
        bool escape = false;
        while (!personQ.empty() && !escape) {
            auto cur = personQ.front(); personQ.pop();
            int x = cur.first;
            int y = cur.second;
            
            for (int dir = 0; dir < 4; dir++) {
                int nx = x + dx[dir];
                int ny = y + dy[dir];
                if (nx < 0 || nx >= r || ny < 0 || ny >= c) {
                    cout << pDist[x][y] + 1 << '\n';
                    escape = true;
                    break;
                }
                if (board[nx][ny] == '#' || board[nx][ny] == '*' || pDist[nx][ny] >= 0) continue;
                // 불이 없는 case도 check 해줘야함!
                if (fDist[nx][ny] != -1 && pDist[x][y] + 1 >= fDist[nx][ny]) continue; 

                personQ.push({nx, ny});
                pDist[nx][ny] = pDist[x][y] + 1;
            }
        }
        
        if (!escape) cout << "IMPOSSIBLE" << '\n'; 
    }
}

 

2. 분석

    불의 거리 bfs를 먼저 처리하고, 사람(상근)의 거리 bfs를 체크해주면 된다. 조금 다른 것은 escape 변수를 둬서 보드 범위 바깥으로 나가면 탈출한 것이므로 해당 부분을 처리해주는 것을 신경써주면 된다.

// 불이 아얘 없는 Edge case를 신경쓰지 못한 코드
if (pDist[x][y] + 1 >= fDist[nx][ny]) continue;

// 불이 없는 경우까지 신경쓴 올바른 구현
if (fDist[nx][ny] != -1 && pDist[x][y] + 1 >= fDist[nx][ny]) continue;

 

    처음에 테스트케이스는 맞추는데 제출하면 '틀렸습니다' 판정을 받았는데 이 부분을 한참 찾았다. 첫번째 처럼 코드를 짜게 되면 불이 번진 시간보다 사람이 가는 시간이 더 길면 배제하는 것 같아 맞아 보이지만 불이 아얘 없는 경우를 신경쓰지 못한 것이다. 문제에 직접적으로 불이 없을 수도 있다고 써있지는 않지만 테스트 케이스에 그 힌트가 있었다. 

 

문제의 마지막 케이스에 보면 "IMPOSSIBLE"이라 크게 신경쓰지 않았지만 사람과 벽만 있고, 불이 없는 것을 알 수 있다. 즉, 불이 board에 없을 수 있고, 아래와같은 케이스도 가능한 것이다.

// board
# # #
# @ .
# # #

// fDist
-1  -1  -1
-1  -1  -1
-1  -1  -1

// 불이 아얘 없는 Edge case를 신경쓰지 못한 코드
if (pDist[x][y] + 1 >= fDist[nx][ny]) continue;

// 불이 없는 경우까지 신경쓴 올바른 구현
if (fDist[nx][ny] != -1 && pDist[x][y] + 1 >= fDist[nx][ny]) continue;

 

fDist에 모든 원소가 -1이 되어서 불이 없을 때도 항상 continue에 걸려버리게 된다. 그래서 fDist[nx][ny] != -1 && 로 불이 번진 상태에서 pDist + 1이 fDist에 안될 때만 continue를 해줘야한다.

 

3. 시간복잡도

시간 복잡도는 O(n * r * c)가 된다. 100 * 1000 * 1000 = 10^8이므로 1초 안에 수행 가능하다.

 

 

 

'코딩테스트 > BOJ' 카테고리의 다른 글

[BOJ / C++] N-Queen (백트래킹)  (0) 2025.07.13
[BOJ / C++] 상범 빌딩 (BFS)  (0) 2025.07.13
[BOJ / C++] Z (재귀)  (1) 2025.07.11
[BOJ / C++] 하노이 탑 이동 순서 (재귀)  (0) 2025.07.10
[BOJ / C++] 곱셈 (재귀)  (0) 2025.07.09
'코딩테스트/BOJ' 카테고리의 다른 글
  • [BOJ / C++] N-Queen (백트래킹)
  • [BOJ / C++] 상범 빌딩 (BFS)
  • [BOJ / C++] Z (재귀)
  • [BOJ / C++] 하노이 탑 이동 순서 (재귀)
sophon
sophon
sophon 님의 블로그 입니다.
  • sophon
    sophon 님의 블로그
    sophon
    • 카테고리 (172) N
      • 컴퓨터공학 (36)
        • 데이터베이스 (19)
        • 네트워크 (15)
        • 기타 이슈 (2)
      • 프로젝트 (16)
        • Java (8)
        • Spring (4)
        • Docker (4)
      • 코딩테스트 (95) N
        • BOJ (74)
        • 프로그래머스 (7)
        • 프로그래머스 SQL (12) N
        • PS Snippets (2)
      • 🌱 잡담 (22)
        • 자격증 (7)
        • 좋은 시 모음 (12)
        • 책과 영화 (3)
        • 기록 (0)
  • 전체
    오늘
    어제
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
sophon
[BOJ / C++] 불 (BFS)
상단으로

티스토리툴바