본문 바로가기
Language/Java

[백준 | Java] 2573번 빙산

by ㅇ달빛천사ㅇ 2025. 1. 25.
728x90
2573번 / 빙산
빙산

🏷️ 관련 주제 : topic1 topic2 topic3



💦 나의 시도

Try01. 반복문을 이용한 방법

내가 시도한 코드
import java.io.*;
import java.util.*;
public class Main {
    public static void main (String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int N = Integer.parseInt(st.nextToken());  // 행 수
        int M = Integer.parseInt(st.nextToken());  // 열 수
        int[][] map = new int[N][M];
        int[][] meltingSpeed = new int[N][M];
        int[][] copyMeltingSpeed = new int[N][M];
        ArrayList<String> iceberg = new ArrayList<>();


        for (int i = 0; i < N; i++) {
            map[i] = Arrays.stream(br.readLine().split(" ")).mapToInt(Integer::parseInt).toArray();
            for (int j = 0; j < M; j++) {
                if (map[i][j] > 0) {
                    String ice = i + " " + j;
                    iceberg.add(ice);
                }
            }
        }

        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (map[i][j] != 0) {
                    int seaCnt = 0;

                    if (i - 1 >= 0 && map[i - 1][j] == 0) {
                        seaCnt++;
                    }

                    if (j - 1 >= 0 && map[i][j - 1] == 0) {
                        seaCnt++;
                    }

                    if (j + 1 < M && map[i][j + 1] == 0) {
                        seaCnt++;
                    }

                    if (i + 1 < N && map[i + 1][j] == 0) {
                        seaCnt++;
                    }

                    meltingSpeed[i][j] = seaCnt;
                    copyMeltingSpeed[i][j] = seaCnt;
                }
            }
        }

        int time = 0;
        while (!iceberg.isEmpty()) {
            ArrayList<String> copyIceberg = new ArrayList<>(iceberg);

            for (String loc : copyIceberg) {
                int[] index = Arrays.stream(loc.split(" ")).mapToInt(Integer::parseInt).toArray();
                int row = index[0];
                int col = index[1];
                int ice = map[row][col];
                int melt = meltingSpeed[row][col];

                if (melt == 4) {
                    System.out.println(time);
                    return;
                }
                ice = Math.max(0, ice - melt);                

                map[row][col] = ice;

                if (ice == 0) {
                    iceberg.remove(loc);

                    if (row - 1 >= 0 && map[row - 1][col] > 0) {
                        copyMeltingSpeed[row - 1][col]++;
                    } 

                    if (col - 1 >= 0 && map[row][col - 1] > 0) {
                        copyMeltingSpeed[row][col - 1]++;
                    }

                    if (col + 1 < M && map[row][col + 1] > 0) {
                        copyMeltingSpeed[row][col + 1]++;
                    }

                    if (row + 1 < N && map[row + 1][col] > 0) {
                        copyMeltingSpeed[row + 1][col]++;
                    }
                }
            }

            for (int i = 0; i < N; i++) {
                meltingSpeed[i] = copyMeltingSpeed[i].clone();
            }
            time++;

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

❌ 틀렸습니다.

인터넷에서 찾은 반례로 테스트 해 보았는데 아래 테스트 케이스에 대하여 N, M을 입력 받는 부분에서 에러가 남
그런데 이유를 모르겠다.🥺


5 5
0 0 0 0 0
0 1 1 1 0
0 1 0 1 0
0 1 1 1 0
0 0 0 0 0

0

제출해야할 시간이 다 되어서 일단 인터넷에서 찾은 풀이를 제출하였습니다.



📑제출 기록 및 오답 원인


💯 해결 방법

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

class IceBerg {
    int x;
    int y;

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

public class Main {
    static int[] rangeX = { -1, 0, 1, 0 };
    static int[] rangeY = { 0, 1, 0, -1 };

    static int N, M;
    static int[][] map;

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        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 ans = 0;
        int cnt = 0;

        // 빙하가 2개 이상 분리될 경우 반복문을 종료.
        // 빙하가 다 녹아버렸을 경우, 0을 출력.
        while ((cnt = SeparateNum()) < 2) {
            if (cnt == 0) {
                ans = 0;
                break;
            }

            Melt();
            ans++;
        }

        bw.write(ans + "\n");
        bw.flush();
        bw.close();
        br.close();
    }

    // 빙하가 분리된 개수를 구하는 함수.
    public static int SeparateNum() {
        boolean[][] visited = new boolean[N][M];

        int cnt = 0;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (map[i][j] != 0 && !visited[i][j]) {
                    DFS(i, j, visited); // DFS 방식을 통해 총 몇개의 빙하로 나누어졌는지 구할 수 있음.
                    cnt++;
                }
            }
        }
        return cnt;
    }

    public static void DFS(int x, int y, boolean[][] visited) {
        visited[x][y] = true;

        int dx, dy;
        for (int i = 0; i < 4; i++) {
            dx = x + rangeX[i];
            dy = y + rangeY[i];

            if (dx < 0 || dy < 0 || dx >= N || dy >= M) {
                continue;
            }

            if (map[dx][dy] != 0 && !visited[dx][dy]) {
                DFS(dx, dy, visited);
            }
        }
    }

    // 빙하를 녹이는 함수.
    public static void Melt() {
        Queue<IceBerg> q = new LinkedList<>();

        // visited 배열을 만드는 이유

        // visited 배열이 없다면,
        // 만약 1 2 가 있는 상태에서 1이 먼저 녹아서 0이 될 경우
        // 2는 녹아서 없어진 1 자리도 0이라고 판단하여
        // 필요 이상으로 더 많은 값을 녹이게 되어 버림.
        boolean[][] visited = new boolean[N][M];
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (map[i][j] != 0) {
                    q.offer(new IceBerg(i, j));
                    visited[i][j] = true;
                }
            }
        }

        int dx, dy;
        while (!q.isEmpty()) {
            IceBerg ice = q.poll();

            int seaNum = 0; // 빙하 상하좌우에 존재하는 바다 영역의 수.

            for (int i = 0; i < 4; i++) {
                dx = ice.x + rangeX[i];
                dy = ice.y + rangeY[i];

                if (dx < 0 || dy < 0 || dx >= N || dy >= M) {
                    continue;
                }

                if (!visited[dx][dy] && map[dx][dy] == 0) {
                    seaNum++;
                }
            }

            if (map[ice.x][ice.y] - seaNum < 0) {
                map[ice.x][ice.y] = 0;
            } else {
                map[ice.x][ice.y] -= seaNum;
            }
        }
    }
}

🏷️ 문제 풀면서 참고한 블로그

 

728x90


Top