자바칩

[백준 / Java] 1743: 음식물 피하기 (BFS) 본문

알고리즘/백준

[백준 / Java] 1743: 음식물 피하기 (BFS)

아기제이 2024. 6. 17. 19:42
728x90

난이도: Silver 1

문제: https://www.acmicpc.net/problem/1743

 

문제

코레스코 콘도미니엄 8층은 학생들이 3끼의 식사를 해결하는 공간이다. 그러나 몇몇 비양심적인 학생들의 만행으로 음식물이 통로 중간 중간에 떨어져 있다. 이러한 음식물들은 근처에 있는 것끼리 뭉치게 돼서 큰 음식물 쓰레기가 된다. 

이 문제를 출제한 선생님은 개인적으로 이러한 음식물을 실내화에 묻히는 것을 정말 진정으로 싫어한다. 참고로 우리가 구해야 할 답은 이 문제를 낸 조교를 맞추는 것이 아니다. 

통로에 떨어진 음식물을 피해가기란 쉬운 일이 아니다. 따라서 선생님은 떨어진 음식물 중에 제일 큰 음식물만은 피해 가려고 한다. 

선생님을 도와 제일 큰 음식물의 크기를 구해서 “10ra"를 외치지 않게 도와주자.

입력

첫째 줄에 통로의 세로 길이 N(1 ≤ N ≤ 100)과 가로 길이 M(1 ≤ M ≤ 100) 그리고 음식물 쓰레기의 개수 K(1 ≤ K ≤ N×M)이 주어진다.  그리고 다음 K개의 줄에 음식물이 떨어진 좌표 (r, c)가 주어진다.

좌표 (r, c)의 r은 위에서부터, c는 왼쪽에서부터가 기준이다. 입력으로 주어지는 좌표는 중복되지 않는다.

출력

첫째 줄에 음식물 중 가장 큰 음식물의 크기를 출력하라.


 

BFS 알고리즘을 잘 이해했으면 쉽게 풀 수 있는 문제다.

크기를 체크할 때는 크기 체크 변수 count를 2로 초기화해서 새로운 칸에 방문할 때마다 count를 1씩 증가시키면 된다.

그리고 마지막에 방문한 (x, y)에 설정된 숫자를 최댓값 변수에 갱신하면 된다.

 

주석에 한 줄 한줄 설명을 자세히 적어 놓았다. 

코드를 바로 보자.

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
73
74
75
76
77
78
79
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 P1743_음식물피하기 {
    static int N, M;                    // 통로의 세로, 가로 길이
    static int[] dx = {-1010};    // 상, 하 이동
    static int[] dy = {0-101};    // 좌, 우 이동
    static int[][] area;                // 2차원 통로 배열
    static boolean[][] visited;            // 2차원 방문 배열
    static int max;                        // 가장 큰 음식물의 크기
    
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());        // 통로의 세로 길이 입력 받기
        M = Integer.parseInt(st.nextToken());        // 통로의 가로 길이 입력 받기
        int K = Integer.parseInt(st.nextToken());    // 음식물 쓰레기의 개수
        area = new int[N + 1][M + 1];                // 통로 배열 세로, 가로 크기 초기화
        visited = new boolean[N + 1][M + 1];        // 방문 배열 세로, 가로 크기 초기화
        
        // 통로 배열 초기화
        for (int k = 0; k < K; k++) {
            st = new StringTokenizer(br.readLine());
            int r = Integer.parseInt(st.nextToken());    // 음식물의 x좌표
            int c = Integer.parseInt(st.nextToken());    // 음식물의 y좌표
            area[r][c] = 1;        // 해당 좌표에 음식물 생성
        }
        
        for (int i = 1; i <= N; i++) {
            for (int j = 1; j <= M; j++) {
                // 해당 칸을 방문하지 않았거나, 해당 칸에 음식물이 있다면
                if (!visited[i][j] && area[i][j] != 0) {
                    bfs(i, j);    // 해당 칸부터 bfs 수행
                }
            }
        }
        
        System.out.println(max);    // 가장 큰 음식물의 크기 출력
    }
    
    public static void bfs(int a, int b) {
        Queue<int[]> queue = new LinkedList<>();    // bfs 수행을 위한 큐 생성
        queue.add(new int[] {a, b});    // 현재 칸을 큐에 삽입
        visited[a][b] = true;            // 현재 칸을 방문 체크
        int count = 2;                    // 현재 칸은 1이고, 다음 칸부터 2로 체크할 카운트
        
        while (!queue.isEmpty()) {
            int[] now = queue.poll();    // 현재 칸을 큐에서 뽑기
            
            for (int i = 0; i < 4; i++) {
                int x = now[0+ dx[i];        // 인접 칸의 x좌표
                int y = now[1+ dy[i];        // 인접 칸의 y좌표
                
                // 인접 칸의 인덱스가 유효하지 않다면 건너뛰기
                if (x < 1 || y < 1 || x > N || y > M) {
                    continue;
                }
                
                // 인접 칸을 이미 방문했거나, 음식물 쓰레기가 없는 칸이라면 건너뛰기
                if (visited[x][y] || area[x][y] == 0) {
                    continue;
                }
                
                queue.add(new int[] {x, y});    // 인접 칸을 큐에 삽입
                visited[x][y] = true;            // 인접 칸을 방문 체크
                area[x][y] = count++;            // 인접 칸 카운트 1 증가
                a = x;        // 최근 방문한 x좌표 갱신
                b = y;        // 최근 방문한 y좌표 갱신
            }
        }
        
        max = Math.max(max, area[a][b]);    // 음식물의 최댓값 갱신
    }
}
 
cs