본문 바로가기
알고리즘/알고리즘 문제풀이

[BOJ-5427] 불(JAVA)

by E145 2021. 9. 29.
반응형

백준 5427 불

 

 

5427번: 불

상근이는 빈 공간과 벽으로 이루어진 건물에 갇혀있다. 건물의 일부에는 불이 났고, 상근이는 출구를 향해 뛰고 있다. 매 초마다, 불은 동서남북 방향으로 인접한 빈 공간으로 퍼져나간다. 벽에

www.acmicpc.net

 

문제 설명

 

 - 상근이는 빈 공간과 벽으로 이루어진 건물에 갇혀있다.

 

 - 건물의 일부에는 불이 났고, 상근이는 출구를 향해 뛰고 있다.

 

 - 매 초마다, 불은 벽에 붙지 않으면서 동서남북 방향으로 인접한 빈 공간에 퍼져나간다.

 

 - 상근이도 동서남북 인접한 칸으로 이동할 수 있고 통과할 수 없으며, 이동시 1초가 걸린다.

 

 - 불이 옮겨진 칸 또는 이제 불이 붙으려는 칸으로 이동할 수 없다.

 

 - 상근이가 불이 옮겨옴과 동시에 다른 칸으로 이동할 수 있다.

 

 - 빌딩의 지도가 주어졌을 때, 얼마나 빨리 빌딩을 탈출할 수 있는지 구하라.

 

 - 각 테스트 케이스마다 빌딩을 탈출하는데 가장 빠른 시간을 출력한다. 빌딩을 탈출할 수 없으면 "IMPOSSIBLE"을 출력한다.

 


 

입력 값

 

 - 첫째 줄에 테스트 케이스 개수가 주어진다. 테스트 케이스는 최대 100개이다.

 

 - 각 테스트 케이스의 첫째 줄에는 빌딩 지도의 너비와 높이 w, h 가 주어진다.

   ( 1 <= w, h <= 1,000 )

 

 - 다음 h개 줄에는 w개의 문자, 빌딩의 지도가 주어진다.

   '.' => 빈 공간 / '#' => 벽 / '@' => 상근이의 시작 위치 / '*' => 불

 

 - 각 지도의 @의 개수는 하나이다.

 


 

 

예제

 


 

 

문제 분석

 

 - 이 문제에서 상근이가 이동할 수 있는 경우는 벽이 아니면서 불이 붙지 않는 빈 공간이다.

 

 - 즉, 불보다 먼저 빈 공간에 간다면 이동할 수 있다는 것이다.

 

 - 해당 빈 공간에 불보다 먼저 왔는지 어떻게 판단할 수 있을까?

 

 - 간단하게 생각하면, BFS를 이용하여 알 수 있다.

 

탐색 알고리즘 - 너비 우선 탐색(Breadth First Search, BFS)

너비 우선 탐색(Breadth First Search, BFS) 너비 우선 탐색이란?  - 임의의 노드에서 인접한 노드를 먼저 모두 탐색하고 다음 단계로 넘어간다.  - 순환 알고리즘의 형태  - 그래프 탐색 시 방문 노드를

9327144.tistory.com

 

 

 - 먼저 불이 빈 공간으로 이동할 수 있는 최소 횟수를 BFS를 이용하여 구한다.

   예를 들어, #*# 와 같은 빌딩이 주어지면, 불이 이동할 수 있는 최소 횟수는 #0# 와 같다.

                 #.#                                                                              #1#

                 #.#                                                                              #2#

 

- 그 이후 상근이가 빈 공간으로 이동했을 때 불보다 먼저 이동할 수 있는지를 BFS를 이용하여 구하면 된다.

 

 - 결론적으로 정리하자면

   1. BFS를 이용하여 불이 모든 공간에 이동할 수 있는 최소 이동 횟수를 구한다.

   2. BFS를 이용하여 상근이가 모든 공간에 이동할 수 있는 최소 이동 횟수를 구한다.

      상근이는 빈 공간에 도착했을 때 불보다 빠르게 도착하여야 한다.

   3. 상근이가 모든 공간을 살펴보면서 밖으로 탈출하는 경우(빌딩 범위 밖으로 나가는 경우)에는 그 횟수를 리턴하고

      모든 경우를 살펴보더라도 탈출할 수 없다면, "IMPOSSIBLE"을 리턴한다.

 


 

 

소스 코드

 

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

// https://www.acmicpc.net/problem/5427
// 불
public class Main {

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

    public static void main(String[] args) throws IOException {

        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));

        int tc = Integer.parseInt(bf.readLine());

        for(int t=0;t<tc;t++){

            StringTokenizer st = new StringTokenizer(bf.readLine());

            int X = Integer.parseInt(st.nextToken());
            int Y = Integer.parseInt(st.nextToken());

            char boards[][] = new char[Y][X];
            int fire[][] = new int[Y][X];
            int visited[][] = new int[Y][X];
            Queue<Pair> q = new LinkedList<>();

            Pair startNode=null;

            for(int i=0;i<Y;i++){
                String s = bf.readLine();
                for(int j=0;j<X;j++){
                    visited[i][j]=Integer.MAX_VALUE;
                    fire[i][j]=Integer.MAX_VALUE;
                    boards[i][j]=s.charAt(j);
                    if(boards[i][j]=='*'){
                        q.add(new Pair(i,j));
                        fire[i][j]=0;
                    }

                    if(boards[i][j]=='@'){
                        startNode = new Pair(i,j);
                        visited[i][j]=0;
                    }
                }
            }

            while(!q.isEmpty()){

                Pair nowPair = q.poll();
                
                for(int d=0;d<4;d++){

                    int ny = nowPair.y+dy[d];
                    int nx = nowPair.x+dx[d];

                    int cnt = fire[nowPair.y][nowPair.x]+1;

                    if(ny < 0 || nx < 0 || ny >= Y || nx >= X || boards[ny][nx]=='#' || fire[ny][nx] <= cnt){
                        continue;
                    }

                    fire[ny][nx]=cnt;

                    q.add(new Pair(ny,nx));

                }
            }
            
            q.add(startNode);

            int result=-1;

            while (!q.isEmpty() && result==-1){

                Pair nowPair = q.poll();

                for(int d=0;d<4;d++){

                    int ny = nowPair.y+dy[d];
                    int nx = nowPair.x+dx[d];

                    int cnt = visited[nowPair.y][nowPair.x]+1;

                    if(ny < 0 || nx < 0 || ny >= Y || nx >= X ){
                        result=cnt;
                        break;
                    }

                    if(boards[ny][nx]=='#' || visited[ny][nx] <= cnt || fire[ny][nx] <= cnt){
                        continue;
                    }

                    visited[ny][nx]=cnt;

                    q.add(new Pair(ny,nx));

                }

            }
            if(result==-1){
                System.out.println("IMPOSSIBLE");
            }
            else{
                System.out.println(result);
            }
        }

    }

    static class Pair{
        int y,x;

        public Pair(int y, int x) {
            this.y = y;
            this.x = x;
        }
    }
}

 

 

반응형

'알고리즘 > 알고리즘 문제풀이' 카테고리의 다른 글

[BOJ-17609] 회문 (JAVA)  (0) 2021.10.10
[BOJ-7662] 이중 우선순위 큐(C++)  (0) 2021.09.30
[BOJ-2157] 여행(JAVA)  (0) 2021.09.28
[BOJ-9935] 문자열 폭발(JAVA)  (0) 2021.09.27
[BOJ-1107] 리모컨(JAVA)  (0) 2021.09.26

댓글