Algorithm/baekjoon

빙산

마닐라 2022. 7. 27. 18:31

📍 문제 설명

https://www.acmicpc.net/problem/2573

 

2573번: 빙산

첫 줄에는 이차원 배열의 행의 개수와 열의 개수를 나타내는 두 정수 N과 M이 한 개의 빈칸을 사이에 두고 주어진다. N과 M은 3 이상 300 이하이다. 그 다음 N개의 줄에는 각 줄마다 배열의 각 행을

www.acmicpc.net

 

💡 접근

bfs 문제였는데 큐가 2가지 필요했다.

1. 빙산을 한번에 녹이기 위한 큐

2. 두 덩어리 이상으로 분리되어있는지 확인하기 위한 큐

 

👩‍💻 코드

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

public class Main {
    static int[] arr, dx = {-1, 1, 0, 0}, dy = {0, 0, -1, 1};
    static int[][] board;
    static boolean[][] visited;
    static int n, m, k, t, num, cnt, second;
    static ArrayList<Integer> list = new ArrayList<>();
    static Queue<Point> q = new LinkedList<>();

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

        board = new int[n][m];
        visited = new boolean[n][m];
        for (int i = 0; i < n; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < m; j++) {
                board[i][j] = Integer.parseInt(st.nextToken());
                if(board[i][j] != 0) q.add(new Point(i, j, board[i][j]));
            }
        }

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

    private static int bfs() {
        while (!q.isEmpty()) {
            int len = q.size();
            for(int i = 0; i < len; i++) {
                Point cp = q.poll();

                int cnt = 0;
                //상하좌우 확인해서 바닷물 몇 개인지 확인
                for(int j = 0; j < 4; j++) {
                    int nx = cp.x + dx[j];
                    int ny = cp.y + dy[j];
                    if(nx<0 || ny<0 || nx>=n || ny>=m) continue;
                    if(board[nx][ny] == 0) cnt++;
                }
                //일단 바닷물 갯수만큼 빼서 큐에 다시 넣어놓기
                q.offer(new Point(cp.x, cp.y, board[cp.x][cp.y]-cnt));
            }

            //모든 좌표 다 확인했으면 원배열을 갱신시켜주기
            for(int i = 0; i < len; i++) {
                Point cp = q.poll();
                board[cp.x][cp.y] = cp.cnt < 0 ? 0 : cp.cnt;
                //빙산이 남아있을 때만 큐에 다시 넣어주기
                if(cp.cnt > 0) q.offer(new Point(cp.x, cp.y, board[cp.x][cp.y]));
            }
            second++;
            //두 덩어리 이상으로 분리되는지 확인
            if(isMany()) return second;
        }
        return 0;
    }

    private static boolean isMany() {
        visited = new boolean[n][m];
        cnt = 0;
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                //인접한 빙산 모두 방문처리
                if(board[i][j] > 0 && !visited[i][j]) {
                    bfs2(i, j);
                    cnt++;
                }
            }
            if(cnt >= 2) return true;
        }
        return false;
    }

    private static void bfs2(int x, int y) {
        Queue<Point> mq = new LinkedList<>();
        mq.offer(new Point(x, y));
        while(!mq.isEmpty()) {
            Point cp = mq.poll();
            for(int i = 0; i < 4; i++) {
                int nx = cp.x + dx[i];
                int ny = cp.y + dy[i];

                if(nx<0 || ny<0 || nx>=n || ny>=m || visited[nx][ny] || board[nx][ny] == 0) continue;
                visited[nx][ny] = true;
                mq.offer(new Point(nx, ny));
            }
        }
    }

    private static class Point {
        private int x;
        private int y;
        private int cnt;

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

        public Point(int x, int y, int cnt) {
            this.x = x;
            this.y = y;
            this.cnt = cnt;
        }

        @Override
        public String toString() {
            return "Point{" +
                    "x=" + x +
                    ", y=" + y +
                    ", cnt=" + cnt +
                    '}';
        }
    }
}

'Algorithm > baekjoon' 카테고리의 다른 글

직사각형 탈출  (0) 2022.07.27
움직이는 미로 탈출  (0) 2022.07.27
말이 되고픈 원숭이  (0) 2022.07.27
숫자고르기  (0) 2022.07.26
샘터  (0) 2022.07.26