ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준 7576번] 토마토 (자바)
    Algorithm/BFS 2022. 5. 13. 21:46

     

    백준알고리즘 7576번 : 토마토 (Solved.ac 난이도 Gold5)

     

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

     

    7576번: 토마토

    첫 줄에는 상자의 크기를 나타내는 두 정수 M,N이 주어진다. M은 상자의 가로 칸의 수, N은 상자의 세로 칸의 수를 나타낸다. 단, 2 ≤ M,N ≤ 1,000 이다. 둘째 줄부터는 하나의 상자에 저장된 토마토

    www.acmicpc.net

     

     

     

    전형적인 BFS문제이다만.. 나는 DFS로 몇 번 시도해보고서야 완전 틀린 해석이었다는 걸 깨달았다.


    DFS로 하게되었을 때의 문제점이라면, 각 구역마다 한번의 탐색으로 끝내도 될 것을 계속 접근하여 비효율적으로 만드는 것이다.

    잘 익은 토마토를 기준으로 너비 우선탐색으로 뻗어나가면, 애초에 검증이 많이 필요없고(며칠 째에 익은 토마토인가? 늦게(혹은 빨리) 탐색한 것은 아닌가? 에 대한 검증이 필요없다., 안익은 토마토인지에 대한 검증만 하면된다.)

    따라서 속도가 빨라진다.

     

     

     

    BFS와 DFS의 극명한 차이는 Queue를 사용하느냐? 재귀를 사용하느냐? 로 보인다.

     

    탐색 방식의 차이는 Queue와 재귀의 구조를 떠올려보면 납득이 간다.

     

    재귀는 메소드가 메소드를 연이어 호출하는 만큼, 지금의 토마토 문제에서 필요한 방법과 같이 0,0 지점을 기준으로 상(0, 1), 하(0, -1), 좌(-1, 0), 우(1, 0)를 최우선적으로 비교할 수없다.

     

    상(上)을 먼저 탐색하다보면, (0, 1)을 탐색하고, 연이어서 호출된 상하좌우 탐색 메소드는 (0, 2) , (0, 3) 등등 계속 위로만 탐색하다가 행렬의 끝부분에 이르러서야 다른 방향을 탐색할 것이다.

     

    반대로 Queue는 메소드가 메소드를 호출하지 않는다. 메소드가 Queue에 탐색 대상을 add 및 poll하도록 설정해주면 됟나.

     

    상, 하, 좌, 우를 한번씩 탐색하라고하면, 기존 탐색대상이었던 (0, 0)을 Queue에서 poll하고, (0, 1), (0, -1), (-1, 0), (1, 0)를 Queue에 add하게 된다. 마찬가지로 (0, 1)이 poll되어 새로운 탐색대상이 된다하더라도, (0, 1) 기준의 상하좌우 (0, 2, (0, 0), (-1, 1), (1, 1)는 기존 Queue에 담겨있던 (0, -1), (-1, 0), (1, 0) 이후에 탐색하게 된다.

     

     

    풀이 과정


    1. 토마토 밭의 정보를 2차원 배열로 받는다. 잘익은 토마토(숫자 1인 토마토)들의 x, y축을 새로운 type의 변수 TomatoPos로 정의하고 Queue에 추가한다.
    2. bfs 메소드를 돌린다.
    2-1. 이 bfs 메소드는 Queue가 빌때까지 수행되는데, Queue는 받아두었던 잘익은 토마토의 위치를 기억했다가, 상하좌우에 안익은 토마토가 있는지 검증하고 이를 Queue에 다시 add한다. 토마토 밭에 옮긴 대상의 위치 값은 기존의 0에서 본 position의 숫자 +1로 바꿔주어 며칠만에 익었는지 count하는 용도로 사용한다.
    3. Queue가 비었다면 2차원 배열을 최종적으로 돌면서 0이 남아있다면 -1을, 그렇지 않다면 최대 일수를 출력한다. 

     

     

     

    ▽ 정답 소스 보기

    더보기
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.LinkedList;
    import java.util.Queue;
    import java.util.StringTokenizer;
    
    public class Main {// No7576 : 토마토_BFS
        static int[][] arr;
        static Queue<TomatoPos> queue = new LinkedList<>();
    
        public static void main(String[] args) throws IOException {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            String[] xy = br.readLine().split(" ");
            int x = Integer.parseInt(xy[0]);
            int y = Integer.parseInt(xy[1]);
            arr = new int[x][y];
    
            for (int i = 0; i < y; i++) {
                StringTokenizer st = new StringTokenizer(br.readLine());
                for (int j = 0; j < x; j++) {
                    arr[j][i] = Integer.parseInt(st.nextToken());
                    if (arr[j][i] == 1) {
                        queue.add(new TomatoPos(j, i));
                    }
                }
            }
            System.out.println(bfs());
    
        }
    
        public static int bfs() {
            while (!queue.isEmpty()) {
                TomatoPos tomato = queue.poll();
                int x = tomato.x;
                int y = tomato.y;
                for (int i = -1; i < 2; i += 2) {
                    if (x + i >= 0 && x + i < arr.length && arr[x + i][y] == 0) {
                        arr[x + i][y] = arr[x][y] + 1;
                        queue.add(new TomatoPos(x + i, y));
                    }
                }
                for (int j = -1; j < 2; j += 2) {
                    if (y + j >= 0 && y + j < arr[0].length && arr[x][y + j] == 0) {
                        arr[x][y + j] = arr[x][y] + 1;
                        queue.add(new TomatoPos(x, y + j));
                    }
                }
            }
    
            int max = 0;
            stop:
            for (int i = 0; i < arr.length; i++) {
                for (int j = 0; j < arr[0].length; j++) {
                    if (arr[i][j] == 0) {
                        max = 0;
                        break stop;
                    }
                    if (arr[i][j] > max) {
                        max = arr[i][j];
                    }
                }
            }
            return max - 1;
        }
    }
    
    class TomatoPos {
        int x;
        int y;
    
        public TomatoPos(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

     

     

     

     

     

    푸는데 3년이나 걸리다니;

    'Algorithm > BFS' 카테고리의 다른 글

    [백준 14502번] 연구소(자바)  (0) 2022.05.14

    댓글

Designed by Tistory.