백준 빙산

KIMYEONGJUN·2026년 3월 9일
post-thumbnail

문제

내가 생각했을때 문제에서 원하는부분

첫 줄에는 이차원 배열의 행의 개수와 열의 개수를 나타내는 두 정수 N과 M이 한 개의 빈칸을 사이에 두고 주어진다.
N과 M은 3 이상 300 이하이다.
그 다음 N개의 줄에는 각 줄마다 배열의 각 행을 나타내는 M개의 정수가 한 개의 빈 칸을 사이에 두고 주어진다.
각 칸에 들어가는 값은 0 이상 10 이하이다.
배열에서 빙산이 차지하는 칸의 개수, 즉, 1 이상의 정수가 들어가는 칸의 개수는 10,000 개 이하이다.
배열의 첫 번째 행과 열, 마지막 행과 열에는 항상 0으로 채워진다.

첫 줄에 빙산이 분리되는 최초의 시간(년)을 출력한다.
만일 빙산이 다 녹을 때까지 분리되지 않으면 0을 출력한다.

내가 이 문제를 보고 생각해본 부분

전체 빙산 정보를 2차원 배열 map에 저장한다. 
배열의 각 칸 값은 빙산 높이이며, 0은 바다를 나타낸다.
매년 빙산이 바닷물에 접한 부분만큼 녹는데, 각 빙산 칸 주변 4방향(동서남북)의 0(바다) 칸 개수를 세어 그만큼 빙산 높이를 감소시킨다. 
이 작업은 melt() 메서드에서 수행해준다.
빙산이 얼만큼 녹았는지 임시 배열 temp에 계산한 후 복사하여 상태를 갱신해준다.
매년 빙산은 분리된 덩어리(연결 요소) 개수를 확인한다. 
빙산이 한 덩어리는 1개, 둘 이상으로 나뉘면 2 이상이 된다.
분리된 덩어리 수를 계산하는 countIceberg() 메서드는 방문 여부를 체크하는 2차원 배열 visited를 만들어 BFS 탐색으로 연결된 빙산을 모두 방문 처리하며 덩어리를 센다.
BFS 탐색은 bfs() 메서드이며, 시작 칸을 큐에 넣어 인접한 빙산 칸들을 모두 방문한다.
반복하면서 빙산 덩어리가 2개 이상 생길 때 그 때의 연도를 출력하고 종료한다.
만약 모든 빙산이 다 녹아 분리되는 순간이 없으면 0을 출력한다.

코드로 구현

package baekjoon.baekjoon_33;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
import java.util.Queue;
import java.util.LinkedList;

// 백준 2573번 문제
public class Main1321 {
    static int N, M;
    static int[][] map;
    static int[] dx = {0, 0, -1, 1};
    static int[] dy = {-1, 1, 0, 0};

    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());
        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());
            }
        }

        int year = 0;
        while (true) {
            year++;
            melt();
            int count = countIceberg();
            if (count == 0) {
                System.out.println(0);
                break;
            }
            if (count >= 2) {
                System.out.println(year);
                break;
            }
        }
        br.close();
    }

    static void melt() {
        int[][] temp = new int[N][M];

        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (map[i][j] > 0) {
                    int seaCount = 0;
                    for (int d = 0; d < 4; d++) {
                        int nx = i + dx[d];
                        int ny = j + dy[d];
                        if (nx >= 0 && nx < N && ny >= 0 && ny < M && map[nx][ny] == 0) {
                            seaCount++;
                        }
                    }
                    temp[i][j] = map[i][j] - seaCount;
                    if (temp[i][j] < 0) temp[i][j] = 0;
                }
            }
        }
        map = temp;
    }

    static int countIceberg() {
        boolean[][] visited = new boolean[N][M];
        int count = 0;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (map[i][j] > 0 && !visited[i][j]) {
                    bfs(i, j, visited);
                    count++;
                }
            }
        }
        return count;
    }

    static void bfs(int x, int y, boolean[][] visited) {
        Queue<int[]> queue = new LinkedList<>();
        queue.offer(new int[]{x, y});
        visited[x][y] = true;

        while (!queue.isEmpty()) {
            int[] cur = queue.poll();
            int cx = cur[0];
            int cy = cur[1];

            for (int d = 0; d < 4; d++) {
                int nx = cx + dx[d];
                int ny = cy + dy[d];
                if (nx >= 0 && nx < N && ny >= 0 && ny < M) {
                    if (map[nx][ny] > 0 && !visited[nx][ny]) {
                        visited[nx][ny] = true;
                        queue.offer(new int[]{nx, ny});
                    }
                }
            }
        }
    }
}

마무리

코드와 설명이 부족할수 있습니다. 코드를 보시고 문제가 있거나 코드 개선이 필요한 부분이 있다면 댓글로 말해주시면 감사한 마음으로 참고해 코드를 수정 하겠습니다.

profile
Junior backend developer

0개의 댓글