CS/Algorism

[백준] 7576. 토마토

olsohee 2023. 12. 26. 16:36

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

 

7576번: 토마토

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

www.acmicpc.net

https://olsohee.tistory.com/44 이 문제와 마찬가지로 bfs로 탐색하면서 이전 값에 + 1을 해주어 토마토가 익는데 걸리는 일수를 구하면 된다.

 

주의할 점은 우선 처음에 그래프 값을 입력받을 때 익은 토마토의 위치를 큐에 넣어주어야 한다. 그리고 큐에서 토마토의 위치를 빼서 해당 위치의 사방면을 탐색하고, 아직 익지 않은 토마토인 경우 이전 값 + 1을 저장해주면 된다. 그리고 또 다시 큐에 넣으면 된다.

 

포인트는 큐는 선입선출이고, 처음에 그래프 값을 입력받을 때 익은 토마토들의 위치를 먼저 큐에 넣었기 때문에, 이들이 먼저 bfs의 시작점이 된다는 것이다. 그리고 이미 방문해서 이전 값 + 1로 값이 채워진 곳은 중복 방문하지 않기 때문에 "최소" 일수가 저장되는 것이다. 

 

큐가 비면 bfs가 끝난다. 즉 더이상 번질 수 없다는 것이다. 그러면 이제 그래프를 탐색해서 가장 큰 값이 답이 된다. 그러나 만약 익지 않은 토마토가 있다면, 즉 그래프 값이 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;

// 시간복잡도: O(V + E)
// = O(n * m + 4V)
// = 1,000,000 + 4,000,000 = 5,000,000
public class Main {

    static int m; // 가로
    static int n; // 세로
    static int[][] map;
    static boolean[][] visited;
    static Queue<Pair> que = new LinkedList<>();
    static int[] dx = {1, -1, 0, 0};
    static int[] dy = {0, 0, 1, -1};

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        m = Integer.parseInt(st.nextToken());
        n = Integer.parseInt(st.nextToken());
        map = new int[n][m];

        for (int i = 0; i < n; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < m; j++) {
                map[i][j] = Integer.parseInt(st.nextToken());
                if (map[i][j] == 1) {
                    que.offer(new Pair(i, j)); // 익은 토마토들은 큐에 넣어주기
                }
            }
        }

        bfs();

        System.out.println(getResult());
    }

    private static void bfs() {
        // 큐에서 익은 토마토를 꺼내서 하나씩 bfs하기
        while (!que.isEmpty()) {
            Pair p = que.poll();

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

                if (ny < 0 || ny >= n || nx < 0 || nx >= m) {
                    continue;
                }

                // 방문하지 않은 경우(0)만 탐색
                if (map[ny][nx] != 0) {
                    continue;
                }

                map[ny][nx] = map[p.y][p.x] + 1;
                que.add(new Pair(ny, nx));
            }
        }
    }

    private static int getResult() {
        int maxDay = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (map[i][j] == 0) { // 익지 않은 토마토가 있으면 -1 출력
                    return -1;
                }
                maxDay = Math.max(maxDay, map[i][j]);
            }
        }
        return maxDay - 1; // 시작점은 날짜에 포함하지 않기 때문에 1을 빼주기
    }

    static class Pair {
        int y, x;

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

'CS > Algorism' 카테고리의 다른 글

[백준] 1541. 잃어버린 괄호  (0) 2023.12.29
[백준] 4179. 불!  (0) 2023.12.28
[백준] 2178. 미로 탐색  (0) 2023.12.26
[백준] 1926. 그림  (1) 2023.12.26
[백준] 10816. 숫자 카드 2  (0) 2023.12.11