코테/백준

[백준/JAVA] 7576번: 토마토

imname1am 2023. 7. 8. 01:18
반응형

🔺 문제

 

7576번: 토마토

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

www.acmicpc.net

 

 

🔺 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import java.util.*;
import java.io.*;
 
public class Main {
    static int[] dx = {0,0,-1,1};
    static int[] dy = {1,-1,0,0};
    
    static int M,N;
    static int[][] map;
    
    static Queue<int[]> queue = new LinkedList<>();
    
    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) {
                    queue.add(new int[] {i, j});
                }
            }
        }
 
        System.out.println(bfs());
        
    }
    
    private static int bfs() {
        while(!queue.isEmpty()) {
            int[] now = queue.poll();
            
            for(int d = 0 ; d < 4 ; d++) {
                int x = now[0+ dx[d];
                int y = now[1+ dy[d];
                
                if(x < 0 || x >= N || y < 0 || y >= M ) continue;
                
                // 토마토가 안 익었다면, 익은 토마토 추가
                if(map[x][y] == 0) {
                    queue.add(new int[] {x, y}); // 인접 노드를 큐에 추가
                    map[x][y] = map[now[0]][now[1]] + 1// 🔔 방문 표시 및 최대값 업데이트 🔔 다음 depth = 현재 depth + 1 🔔
                }
            }
            
        }
        
        // 토마토가 모두 익는 최대 날짜 구하기
        int max = Integer.MIN_VALUE;
        
        for(int i = 0 ; i < N ; i++) {
            for(int j = 0 ; j < M ; j++) {
                if(map[i][j] == 0)    return -1;
                max = Math.max(max, map[i][j]);
            }
        }
        
        if(max == 1return 0;        // 토마토가 모두 익은 상태인 경우
        else         return max - 1;  // 걸린 일수 = 최대 날짜 - 1
    }
}
 
cs
✅ 해결 아이디어
BFS
- 최대 일수를 구하는 것이므로, 1로 바꾸는 것이 아닌 기존값 + 1을 해 구함 
- 인접 노드에 대한 방문 표시 : 다음 depth = 현재 depth + 1 (이게 계산 겸 방문 표시)

 

 

52번째 줄을 놓쳤다...

방문 표시는 visited 배열 쓰지 말고,

현재 노드 depth 값 + 1로 하는 것으로...

 

 


🔺 다른 풀이들

- 날짜 구하는 방식만 아주 조오금 다름

 

로그인

 

www.acmicpc.net


💬 느낀 점

방문 배열 visited[][] 가 필요 없는 이유

그냥 map[][] 배열의 값을 업데이트 하면 되는 것이다,,,,,

map[][] 배열 값이 0이면 방문 안 한 거니까...

 

1회독 2회독 3회독 4회독 5회독
V 230810 240106 240618  

 

 

+ 24.01.06 2회독

ArrayDeque을 썼더니 훨씬 빨라졌다.

 

놓친 부분

- 토마토가 저장 초기부터 모두 익은 경우

→ 완전탐색 통해 0을 안 갖고 있을 때의 최댓값을 구해 이 값이 1일 때가 저장 초기부터 모두 익은 상태이므로 0을 출력한다.

 

코드 확인하기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import java.util.*;
import java.io.*;
 
public class Main {
    static int[] dx = {-1100};
    static int[] dy = {00-11};
    
    static int M, N;
    static int[][] map;
    
    static Queue<int[]> q = new ArrayDeque<>();
    static int max = Integer.MIN_VALUE;
    
    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) {
                    q.add(new int[] {i, j});
                }
            }
        }
        
        bfs();
        
        for(int i = 0 ; i < N ; i++) {
            for(int j = 0 ; j < M ; j++) {
                if(map[i][j] == 0) {    // 토마토가 익지 않은 칸이 있다면, -1 출력하고 종료
                    System.out.println(-1);
                    return;
                }
                max = Math.max(max, map[i][j]);
            }
        }
        
        System.out.println(max == 1 ? 0 : max - 1);
    }
    
    private static void bfs() {
        while(!q.isEmpty()) {
            int[] now = q.poll();
            
            for(int d = 0 ;d < 4 ; d++) {
                int nx = now[0+ dx[d];
                int ny = now[1+ dy[d];
                
                if(!inRange(nx, ny))    continue;
                
                if(map[nx][ny] == 0) {    // 익지 않은 토마토 익히기
                    map[nx][ny] = map[now[0]][now[1]] + 1;    // 날짜 누적해 계산하는 겸 방문 처리
                    q.add(new int[] {nx, ny});                    
                }
            }
        }        
    }
    
    private static boolean inRange(int x, int y) {
        return (0 <= x && x < N && 0 <= y && y < M);
    }
}
 
cs


(참고)

 

[백준] 7576번 토마토 - Java, 자바

골드5최소일수를 구하라고 했으니 BFS로 접근해야한다. 문제의 로직은 일반적인 BFS 문제와 유사하다. 하지만 이해가 안가는 부분이 있었다. 토마토에는 주어진 익은 토마토의 개수가 여러 개 일

velog.io

 

[백준 알고리즘] 백준 7576번 토마토 자바(Java)

츄르사려고 코딩하는 코집사입니다. 1. [백준 알고리즘] 백준 7576번 토마토 자바(Java) 1) 문제번호 : 7576번 2) 문제 출처 www.acmicpc.net/problem/7576 7576번: 토마토 첫 줄에는 상자의 크기를 나타내는 두

yongku.tistory.com

 

[BOJ] 백준 7576 - 토마토 (자바)

BFS,,... 오랜만에 BFS 문제 풀려고 했었는데 생각이 않났다. 그래서 시간 두고 다시 풀어봄.아주 단순히 이전 값에 +1 해주면 되는 거였다. 풀이1. 토마토가 익은 점들을 큐에 넣어준다. (동시 다발

zoonvivor.tistory.com

 

반응형