본문 바로가기
알고리즘 문제/백준

[백준] 7578번: 토마토 (Java)

by Lpromotion 2024. 8. 13.

1. 문제설명

토마토는 격자 모양 상자의 칸에 하나씩 보관된다. 익은 토마토의 인접한(상하좌우) 곳에 있는 익지 않은 토마토들만 익은 토마토의 영향을 받아 익게 된다. 창고에 보관된 토마토들이 며칠이 지나면 다 익게 되는지, 그 최소 일수를 구하는 문제이다.

만약, 저장될 때부터 모든 토마토가 익어있는 상태이면 0을 출력, 토마토가 모두 익지 못하는 상황이면 -1을 출력한다.

  • 시간 제한: 1초
  • 메모리 제한: 256MB

 

2. 접근 방식

⇒ 모든 토마토가 익는 최소 시간을 구하는 문제 → BFS

  • 토마토 정보를 담은 `int[][] box`를 사용한다.
  • 상하좌우로 이동할 수 있는 배열(dx, dy)을 사용한다.
  • 익은 토마토를 큐에 추가한다. (위치 정보)
  • 큐가 빌 때까지
    • 큐에서 값을 꺼내, 이 위치의 상하좌우를 탐색한다. (`box[x][y]`)
    • 이동할 수 있는 위치이고, 익지 않은 토마토이면 (`box[nx][ny]`)
      • 날짜 계산을 위해 `box[nx][ny] = box[x][y] + 1`
      • 해당 토마토 위치를 큐에 추가한다.
  • 안 익은 토마토가 있으면 -1을 출력
  • `box`에서 max값을 구하고
    • 이 값이 1이면 처음부터 모든 토마토가 익어있는 상태로 0을 출력
    • 아니면 이 값에 -1한 값을 출력 (최종 날짜)

 

3. 다른 풀이

 

4. 최종 코드

import java.io.*;
import java.util.*;

public class Main {
    static int m, n; // 상자의 가로, 세로 칸의 수
    static int[][] box; // 상자
    static Queue<int[]> q = new ArrayDeque<>(); // 익은 토마토 저장할 큐

    static int[] dx = {-1, 1, 0, 0}; // 왼쪽, 오른쪽
    static int[] dy = {0, 0, -1, 1}; // 앞, 뒤

    static int bfs() {
        while(!q.isEmpty()) { // 큐가 빌 때까지
            int[] pos = q.poll(); // 큐에서 값 꺼냄
            int x = pos[0];
            int y = pos[1];
            for(int i=0; i<4; i++) { // 상하좌우 탐색
                int nx = x + dx[i];
                int ny = y + dy[i];
                if(nx>=0 && nx<n && ny>=0 && ny<m) { // 이동 가능한 위치일 때
                    if(box[nx][ny] == 0) { //  다음 위치의 토마토가 익히지 않은 토마토일 때
                        box[nx][ny] = box[x][y] + 1; // 날짜 세기 위해 -> 현재 위치 값 + 1
                        q.add(new int[]{nx, ny}); // 큐에 다음 위치 추가
                    }
                }
            }
        }

        int day = 0;
        for(int i=0; i<n; i++) {
            for(int j=0; j<m; j++) {
                if(box[i][j] == 0) { // 안 익은 토마토가 있는지 확인
                    return -1; // 결과값 1로 설정
                }
                day = Math.max(day, box[i][j]);
            }
        }

        if (day == 1) { // 처음부투 토마토가 모두 익어있으면
            return 0; // 결과값 0으로 설정
        } else { // 두 가지 조건에 모두 충족하지 않으면
            return day - 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());
        box = new int[n][m];
        for(int i=0; i<n; i++) {
            st = new StringTokenizer(br.readLine());
            for(int j=0; j<m; j++) {
                box[i][j] = Integer.parseInt(st.nextToken());
                if(box[i][j] == 1) // 익은 토마토일 경우
                    q.add(new int[] {i, j}); // 해당 위치를 큐에 추가
            }
        }

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

 

5. 느낀점 or 기억할정보

확실히 골드 문제부터는 스스로 설계를 완벽하게 생각해내기가 어려웠다.

DFS로 푸는 방법이 익숙해져서 BFS로 풀이해야하는 문제가 있으면 더 어렵게 느껴지는 것 같다.

BFS로 푸는 연습이 더 필요한 것 같다.

반응형

댓글