์•Œ๊ณ ๋ฆฌ์ฆ˜/๋ฐฑ์ค€

[ ๋ฐฑ์ค€ / BOJ 21609 ] ์ƒ์–ด ์ค‘ํ•™๊ต ( ์ž๋ฐ” / JAVA )

KIMHYEYUN 2022. 2. 14. 22:16
๋ฐ˜์‘ํ˜•

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

 

21609๋ฒˆ: ์ƒ์–ด ์ค‘ํ•™๊ต

์ƒ์–ด ์ค‘ํ•™๊ต์˜ ์ฝ”๋”ฉ ๋™์•„๋ฆฌ์—์„œ ๊ฒŒ์ž„์„ ๋งŒ๋“ค์—ˆ๋‹ค. ์ด ๊ฒŒ์ž„์€ ํฌ๊ธฐ๊ฐ€ N×N์ธ ๊ฒฉ์ž์—์„œ ์ง„ํ–‰๋˜๊ณ , ์ดˆ๊ธฐ์— ๊ฒฉ์ž์˜ ๋ชจ๋“  ์นธ์—๋Š” ๋ธ”๋ก์ด ํ•˜๋‚˜์”ฉ ๋“ค์–ด์žˆ๊ณ , ๋ธ”๋ก์€ ๊ฒ€์€์ƒ‰ ๋ธ”๋ก, ๋ฌด์ง€๊ฐœ ๋ธ”๋ก, ์ผ๋ฐ˜ ๋ธ”๋ก

www.acmicpc.net

๋ฌธ์ œ ์„ค๋ช…

๊ฒŒ์ž„ NxN์ธ ๊ฒฉ์ž์—์„œ ์ง„ํ–‰, ์ดˆ๊ธฐ์—๋Š” ๋ชจ๋“  ์นธ์— ๋ธ”๋ก์ด ํ•˜๋‚˜์”ฉ ์กด์žฌ
๋ธ”๋ก ๐Ÿ‘‰

  • ๊ฒ€์€์ƒ‰ ๋ธ”๋ก : -1
  • ๋ฌด์ง€๊ฐœ ๋ธ”๋ก : 0
  • ์ผ๋ฐ˜ ๋ธ”๋ก : M๊ฐ€์ง€ ์ƒ‰์ƒ, 1 ~ M

๋ธ”๋ก ๊ทธ๋ฃน : ์—ฐ๊ฒฐ๋œ ๋ธ”๋ก์˜ ์ง‘ํ•ฉ

  • ์ผ๋ฐ˜ ๋ธ”๋ก์€ ์ ์–ด๋„ ํ•˜๋‚˜ ์กด์žฌ
  • ์ผ๋ฐ˜ ๋ธ”๋ก์€ ๋ชจ๋‘ ๊ฐ™์€ ์ƒ‰
  • ๊ฒ€์€์ƒ‰ ๋ธ”๋ก์€ ์กด์žฌ โŒ
  • ๋ฌด์ง€๊ฐœ ๋ธ”๋ก์˜ ๊ฐœ์ˆ˜๋Š” ์ƒ๊ด€ โŒ
  • ๋ธ”๋ก์˜ ๊ฐœ์ˆ˜ >= 2
  • ๊ธฐ์ค€ ๋ธ”๋ก์€ ์ผ๋ฐ˜ ๋ธ”๋ก ์ค‘์—์„œ ํ–‰ ๋ฒˆํ˜ธ๊ฐ€ ๊ฐ€์žฅ ์ž‘์€ ๋ธ”๋ก → ์—ด ๋ฒˆํ˜ธ๊ฐ€ ๊ฐ€์žฅ ์ž‘์€ ๋ธ”๋ก

์˜คํ†  ํ”Œ๋ ˆ์ด ๊ธฐ๋Šฅ

๋ธ”๋ก ๊ทธ๋ฃน์ด ์กด์žฌํ•˜๋Š” ๋™์•ˆ ๋ฐ˜๋ณต

  1. ํฌ๊ธฐ๊ฐ€ ๊ฐ€์žฅ ํฐ ๋ธ”๋ก ๊ทธ๋ฃน์„ ์ฐพ๋Š”๋‹ค. ์—ฌ๋Ÿฌ ๊ฐœ๋ผ๋ฉด ๐Ÿ‘‰
    1) ๋ฌด์ง€๊ฐœ ๋ธ”๋ก์˜ ์ˆ˜๊ฐ€ ๊ฐ€์žฅ ๋งŽ์€ ๊ทธ๋ฃน
    2) ๊ธฐ์ค€ ๋ธ”๋ก์˜ ํ–‰์ด ๊ฐ€์žฅ ํฐ ๊ฒƒ
    3) ๊ธฐ์ค€ ๋ธ”๋ก์˜ ์—ด์ด ๊ฐ€์žฅ ํฐ ๊ฒƒ
  2. 1์—์„œ ์ฐพ์€ ๊ทธ๋ฃน์˜ ๋ธ”๋ก์„ ๋ชจ๋‘ ์ œ๊ฑฐ. $B^2$์ ์„ ํš๋“(B → ๋ธ”๋ก์˜ ๊ฐœ์ˆ˜)
  3. ์ค‘๋ ฅ ์ž‘์šฉ ๐Ÿ‘‰ ๊ฒ€์€์ƒ‰ ๋ธ”๋ก์„ ์ œ์™ธํ•œ ๋ชจ๋“  ๋ธ”๋ก์ด ํ–‰์˜ ๋ฒˆํ˜ธ๊ฐ€ ํฐ ์นธ์œผ๋กœ ์ด๋™, ๋‹ค๋ฅธ ๋ธ”๋ก์ด๋‚˜ ๊ฒฉ์ž์˜ ๊ฒฝ๊ณ„๋ฅผ ๋งŒ๋‚˜๊ธฐ ์ „๊นŒ์ง€
  4. ๊ฒฉ์ž๊ฐ€ 90๋„ ๋ฐ˜์‹œ๊ณ„ ๋ฐฉํ–ฅ์œผ๋กœ ํšŒ์ „
  5. ์ค‘๋ ฅ ์ž‘์šฉ

๋ฌธ์ œ ํ’€์ด

Block ํด๋ž˜์Šค

๋ธ”๋ก ๊ทธ๋ฃน์„ ํ‘œ์‹œํ•˜๋Š” ํด๋ž˜์Šค
์ด ๋ธ”๋ก์˜ ๊ฐœ์ˆ˜(numOfTotal), ๋ฌด์ง€๊ฐœ ๋ธ”๋ก์˜ ๊ฐœ์ˆ˜(numOfRainBow), ๊ธฐ์ค€๋ธ”๋ก์˜ ์ขŒํ‘œ(x, y)
๋น„๊ต ํ•จ์ˆ˜(compareTo)

@Override
public int compareTo(Block o) {
    if (this.numOfTotal == o.numOfTotal) {
        if (this.numOfRainBow == o.numOfRainBow) {
            if(this.x == o.x) return o.y - this.y;
            return o.x - this.x;
        }
        return o.numOfRainBow - this.numOfRainBow;
    }
    return o.numOfTotal - this.numOfTotal;
}

1. ๋ธ”๋ก ๊ทธ๋ฃน๋“ค ์ฐพ๊ธฐ

gameMap[x][y]์„ ๋Œ๋ฉด์„œ, ๊ธฐ๋ณธ ๋ธ”๋ก์ด๊ณ  ๋ฐฉ๋ฌธํ•˜์ง€ ์•Š์€ ์นธ์„ ์ฐพ์Œ
findBlockGroup(x,y,boolean)
boolean์ด true๋ผ๋ฉด ๐Ÿ‘‰ ๋ชจ๋“  ๋ธ”๋ก ๊ทธ๋ฃน๋“ค์„ ์ฐพ๋Š” ๊ฒƒ
boolean์ด false ๐Ÿ‘‰ 2๋ฒˆ์—์„œ ์‚ฌ์šฉ

BFS ์ง„ํ–‰,
์กฐ๊ฑด์— ๋งž๋Š” ๋ธ”๋ก์„ ์ฐพ์œผ๋ฉด total += 1,
total >= 2๋ผ๋ฉด, ๋ธ”๋ก ๊ทธ๋ฃน ๋ฆฌ์ŠคํŠธ์— ์ถ”๊ฐ€!
flag ๐Ÿ‘‰ true,
๋ฌด์ง€๊ฐœ ๋ธ”๋ก์€ ๊ณตํ†ต์œผ๋กœ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, isVisited๋ฅผ false๋กœ ๋ณ€๊ฒฝ

2. ์กฐ๊ฑด์— ๋งž๋Š” ๋ธ”๋ก๊ทธ๋ฃน ๋‚ด ๋ธ”๋ก ์‚ญ์ œ

๋ธ”๋ก ๊ทธ๋ฃน๋“ค์˜ ๋ฆฌ์ŠคํŠธ๋ฅผ Sort ๐Ÿ‘‰ ๋งจ ์•ž์˜ ๋ธ”๋ก๊ทธ๋ฃน(block) ์„ ํƒ
๋‹ค์‹œ findBlockGroup(block.x, block.y, false) ์ง„ํ–‰

๊ทธ ํ›„, removeBlock() ์ง„ํ–‰
์•ž์˜ findBlockGroup์—์„œ isVisited๊ฐ€ true ๊ฐ’์œผ๋กœ ๋ณ€ํ•œ ๋ธ”๋ก๋“ค์„ BLANK = 6์œผ๋กœ ๊ฐ’ ๋ฐ”๊ฟ”์คŒ
ans += Block.numOfTotal * Block.numOfTotal;

3. ์ค‘๋ ฅ ์ž‘์šฉ

gravity()

ํ•œ ์—ด์”ฉ ์ง„ํ–‰ํ•˜๋ฉด์„œ, ์ผ๋ฐ˜ ๋˜๋Š” ๋ฌด์ง€๊ฐœ ๋ธ”๋ก์˜ ๋ฐ‘์˜ ํ–‰์ด ๋น„์–ด์žˆ์œผ๋ฉด ๋‚ด๋ ค์คŒ

4. 90๋„ ๋ฐ˜์‹œ๊ณ„ ํšŒ์ „

rotate()

๋ ์ „์ฒด ์—ด๋ถ€ํ„ฐ 0ํ–‰๋ถ€ํ„ฐ ์ „์ฒด๋กœ ์ด๋™
tmp[i][j] = gameMap[j][N-i-1];

5. ๋‹ค์‹œ ์ค‘๋ ฅ ์ž‘์šฉ

gravity()

์ด ๊ฒƒ์„ ๋ธ”๋ก ๊ทธ๋ฃน๋“ค์ด ๋ฐœ๊ฒฌ๋˜์ง€ ์•Š์„ ๋•Œ๊นŒ์ง€ ์ง„ํ–‰.!!

์ฝ”๋“œ

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main_BOJ_21609_์ƒ์–ด_์ค‘ํ•™๊ต {

    static class Block implements Comparable<Block>{
        int numOfTotal, numOfRainBow, x, y;

        public Block(int numOfTotal, int numOfRainBow, int x, int y) {
            this.numOfTotal = numOfTotal;
            this.numOfRainBow = numOfRainBow;
            this.x = x;
            this.y = y;
        }

        @Override
        public int compareTo(Block o) {
            if (this.numOfTotal == o.numOfTotal) {
                if (this.numOfRainBow == o.numOfRainBow) {
                    if(this.x == o.x) return o.y - this.y;
                    return o.x - this.x;
                }
                return o.numOfRainBow - this.numOfRainBow;
            }
            return o.numOfTotal - this.numOfTotal;
        }
    }

    static int N, M, ans = 0;
    static final int BLACK = 6;
    static int[][] gameMap;
    static boolean[][] isVisited;
    static List<Block> blockGroup;
    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());
        M = Integer.parseInt(stringTokenizer.nextToken());

        gameMap = new int[N][N];

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

        while (true) {
            blockGroup = new ArrayList<>();
            isVisited = new boolean[N][N];
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < N; j++) {
                    if(0 < gameMap[i][j] && gameMap[i][j] <= M && !isVisited[i][j]) findBlockGroup(i, j, true);
                }
            }
            if(blockGroup.isEmpty()) break;

            Collections.sort(blockGroup);
            isVisited = new boolean[N][N];
            findBlockGroup(blockGroup.get(0).x, blockGroup.get(0).y, false);
            removeBlock();
            ans += blockGroup.get(0).numOfTotal * blockGroup.get(0).numOfTotal;
            gravity();
            rotate();
            gravity();
        }

        System.out.println(ans);
    }

    private static void rotate() {
        int[][] tmp = new int[N][N];
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                tmp[i][j] = gameMap[j][N - i - 1];
            }
        }

        for (int i = 0; i < N; i++) {
            System.arraycopy(tmp[i], 0, gameMap[i], 0, N);
        }
    }

    private static void gravity() {
        for (int j = 0; j < N; j++) {
            for (int i = N - 1; i >= 0; i--) {
                if(gameMap[i][j] == BLACK || gameMap[i][j] == -1) continue;
                int dest = i + 1;

                while (true) {
                    if(dest == N) break;
                    if(gameMap[dest][j] == BLACK) dest += 1;
                    else break;
                }
                if(dest == i+1) continue;
                gameMap[dest - 1][j] = gameMap[i][j];
                gameMap[i][j] = BLACK;
            }
        }
    }

    private static void removeBlock() {
        int cnt = 0;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if(isVisited[i][j]){
                    cnt += 1;
                    gameMap[i][j] = BLACK;
                }
            }
        }
    }

    private static void findBlockGroup(int x, int y, boolean flag) {
        Queue<int[]> q = new LinkedList<>();
        int blockColor = gameMap[x][y];
        isVisited[x][y] = true;
        q.add(new int[]{x, y});

        int total = 1;
        int rainbow = 0;
        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 || isVisited[nx][ny]) continue;
                if (gameMap[nx][ny] != 0 && gameMap[nx][ny] != blockColor) continue;

                if (gameMap[nx][ny] == 0) rainbow += 1;
                total += 1;
                isVisited[nx][ny] = true;
                q.add(new int[]{nx, ny});
            }
        }

        if (total >= 2) blockGroup.add(new Block(total, rainbow, x, y));
        if (flag) {
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < N; j++) {
                    if (gameMap[i][j] == 0) isVisited[i][j] = false;
                }
            }
        }
    }
}
728x90
๋ฐ˜์‘ํ˜•