μ•Œκ³ λ¦¬μ¦˜/λ°±μ€€

[ BOJ / λ°±μ€€ 20058 ] λ§ˆλ²•μ‚¬ 상어와 νŒŒμ΄μ–΄μŠ€ν†° ( μžλ°” / JAVA )

KIMHYEYUN 2022. 2. 5. 01:02
λ°˜μ‘ν˜•

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

 

20058번: λ§ˆλ²•μ‚¬ 상어와 νŒŒμ΄μ–΄μŠ€ν†°

λ§ˆλ²•μ‚¬ μƒμ–΄λŠ” νŒŒμ΄μ–΄λ³Όκ³Ό 토넀이도λ₯Ό μ‘°ν•©ν•΄ νŒŒμ΄μ–΄μŠ€ν†°μ„ μ‹œμ „ν•  수 μžˆλ‹€. μ˜€λŠ˜μ€ νŒŒμ΄μ–΄μŠ€ν†°μ„ 크기가 2N × 2N인 격자둜 λ‚˜λˆ„μ–΄μ§„ μ–ΌμŒνŒμ—μ„œ μ—°μŠ΅ν•˜λ €κ³  ν•œλ‹€. μœ„μΉ˜ (r, c)λŠ” 격자의 rν–‰ c

www.acmicpc.net

문제 μ„€λͺ…

λ§ˆλ²•μ‚¬ 상어가 $2^N$X$2^N$ 크기의 μ–ΌμŒνŒμ—μ„œ νŒŒμ΄μ–΄μŠ€ν†° μ—°μŠ΅
A[r][c] : (r,c)에 μžˆλŠ” μ–ΌμŒμ˜ μ–‘

  • 단계 L을 결정해야함 ‼️
    1) μ–ΌμŒνŒμ„ $2^L$X$2^L$의 크기의 λΆ€λΆ„ 격자둜 λ‚˜λˆ”
    2) λͺ¨λ“  λΆ€λΆ„ 격자λ₯Ό μ‹œκ²Œλ°©ν–₯으둜 90도 νšŒμ „
    3) μ–ΌμŒμ΄ μ—†λŠ” μΈμ ‘ν•œ 칸이 2개 이상이면 (r,c)칸의 μ–ΌμŒμ˜ μ–‘ -= 1
  • 이 단계λ₯Ό Q번 μ‹œμ „
  • 좜λ ₯
    1) λ‚¨μ•„μžˆλŠ” μ–ΌμŒ A[r][c]의 ν•©
    2) λ‚¨μ•„μžˆλŠ” μ–ΌμŒ 쀑 κ°€μž₯ 큰 덩어리가 μ°¨μ§€ν•˜λŠ” 칸의 개수

문제 풀이

1) λΆ€λΆ„ 배열을 νšŒμ „

divide(int L) : $2^N$X$2^N$ 크기 μ–ΌμŒνŒμ„ $2^L$X$2^L$의 크기둜 λ‚˜λˆˆλ‹€.
rotate() : $2^L$X$2^L$의 크기의 μ–ΌμŒνŒμ„ νšŒμ „

2) 주변에 μ–ΌμŒμ΄ μ—†λŠ” 칸이 2개 이상인 칸의 μ–ΌμŒ 녹이기

meltIce()
μ–ΌμŒμ€ ν•œ λ²ˆμ— λ™μ‹œμ— λ…Ήμ•„μ•Ό 함‼️
πŸ‘‰ 즉, λ°”λ‘œ λ…Ήμ—¬μ„œλŠ” μ•ˆλŒ tmp[][]에 녹이고 후에 반영

3) κ°€μž₯ 큰 μ–ΌμŒ 덩어리λ₯Ό μ°Ύκ³ , μ°¨μ§€ν•˜λŠ” 칸의 개수 κ΅¬ν•˜κΈ°

findLargestIceberg()
BFS 이용

μ½”λ“œ

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

public class Main_BOJ_20058_λ§ˆλ²•μ‚¬_상어와_νŒŒμ΄μ–΄μŠ€ν†° {
    static int N, Q, ans, totalOfIce;
    static int[][] A;
    static int[] L;
    static int[] dx = {-1, 0, 0, 1};
    static int[] dy = {0, -1, 1, 0};

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer stringTokenizer = new StringTokenizer(br.readLine());

        N = Integer.parseInt(stringTokenizer.nextToken());
        Q = Integer.parseInt(stringTokenizer.nextToken());
        N = (int) Math.pow(2, N);

        A = new int[N][N];
        for (int i = 0; i < N; i++) {
            stringTokenizer = new StringTokenizer(br.readLine());
            for (int j = 0; j < N; j++) {
                A[i][j] = Integer.parseInt(stringTokenizer.nextToken());
            }
        }

        L = new int[Q];
        stringTokenizer = new StringTokenizer(br.readLine());
        for (int i = 0; i < Q; i++) {
            L[i] = Integer.parseInt(stringTokenizer.nextToken());
        }

        for (int i = 0; i < Q; i++) {
            A = divide(L[i]);
            A = meltIce();
        }

        findLargestIceberg();
        System.out.println(totalOfIce);
        System.out.println(ans);
    }

    private static void findLargestIceberg() {
        boolean[][] isVisited = new boolean[N][N];
        Queue<int[]> q = new LinkedList<>();
        ans = 0;
        totalOfIce = 0;

        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if(A[i][j] <= 0 || isVisited[i][j]) continue;

                q.add(new int[]{i, j});
                isVisited[i][j] = true;
                totalOfIce += A[i][j];
                int cnt = 1;
                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(nx < 0 || ny < 0 || N <= nx || N <= ny || A[nx][ny] <= 0 || isVisited[nx][ny]) continue;

                        cnt += 1;
                        isVisited[nx][ny] = true;
                        q.add(new int[]{nx, ny});
                        totalOfIce += A[nx][ny];
                    }
                }

                ans = ans < cnt ? cnt : ans;
            }
        }

    }

    private static int[][] meltIce() {
        int[][] tmp = new int[N][N];

        for (int i = 0; i < N; i++) {
            tmp[i] = Arrays.copyOf(A[i], N);
        }

        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                int cnt = 0;
                if (A[i][j] == 0) continue;
                for (int d = 0; d < 4; d++) {
                    int nx = i + dx[d];
                    int ny = j + dy[d];

                    if (nx < 0 || ny < 0 || N <= nx || N <= ny || A[nx][ny] <= 0) continue;

                    cnt += 1;
                }
                if (cnt < 3) tmp[i][j] -= 1;
            }
        }
        return tmp;
    }

    private static int[][] divide(int L) {
        int[][] tmp = new int[N][N];
        L = (int) Math.pow(2, L);

        for (int i = 0; i < N; i += L) {
            for (int j = 0; j < N; j += L) {
                rotate(i, j, L, tmp);
            }
        }

        return tmp;
    }

    private static void rotate(int x, int y, int L, int[][] tmp) {
        for (int i = 0; i < L; i++) {
            for (int j = 0; j < L; j++) {
                tmp[j + x][y + L - i - 1] = A[i + x][j + y];
            }
        }

    }
}
728x90
λ°˜μ‘ν˜•