https://www.acmicpc.net/problem/21609
๋ฌธ์ ์ค๋ช
๊ฒ์ NxN์ธ ๊ฒฉ์์์ ์งํ, ์ด๊ธฐ์๋ ๋ชจ๋ ์นธ์ ๋ธ๋ก์ด ํ๋์ฉ ์กด์ฌ๋ธ๋ก
๐
- ๊ฒ์์ ๋ธ๋ก : -1
- ๋ฌด์ง๊ฐ ๋ธ๋ก : 0
- ์ผ๋ฐ ๋ธ๋ก : M๊ฐ์ง ์์, 1 ~ M
๋ธ๋ก ๊ทธ๋ฃน
: ์ฐ๊ฒฐ๋ ๋ธ๋ก์ ์งํฉ
- ์ผ๋ฐ ๋ธ๋ก์ ์ ์ด๋ ํ๋ ์กด์ฌ
- ์ผ๋ฐ ๋ธ๋ก์ ๋ชจ๋ ๊ฐ์ ์
- ๊ฒ์์ ๋ธ๋ก์ ์กด์ฌ โ
- ๋ฌด์ง๊ฐ ๋ธ๋ก์ ๊ฐ์๋ ์๊ด โ
- ๋ธ๋ก์ ๊ฐ์ >= 2
- ๊ธฐ์ค ๋ธ๋ก์ ์ผ๋ฐ ๋ธ๋ก ์ค์์ ํ ๋ฒํธ๊ฐ ๊ฐ์ฅ ์์ ๋ธ๋ก → ์ด ๋ฒํธ๊ฐ ๊ฐ์ฅ ์์ ๋ธ๋ก
์คํ ํ๋ ์ด ๊ธฐ๋ฅ
๋ธ๋ก ๊ทธ๋ฃน์ด ์กด์ฌํ๋ ๋์ ๋ฐ๋ณต
- ํฌ๊ธฐ๊ฐ ๊ฐ์ฅ ํฐ ๋ธ๋ก ๊ทธ๋ฃน์ ์ฐพ๋๋ค. ์ฌ๋ฌ ๊ฐ๋ผ๋ฉด ๐
1) ๋ฌด์ง๊ฐ ๋ธ๋ก์ ์๊ฐ ๊ฐ์ฅ ๋ง์ ๊ทธ๋ฃน
2) ๊ธฐ์ค ๋ธ๋ก์ ํ์ด ๊ฐ์ฅ ํฐ ๊ฒ
3) ๊ธฐ์ค ๋ธ๋ก์ ์ด์ด ๊ฐ์ฅ ํฐ ๊ฒ - 1์์ ์ฐพ์ ๊ทธ๋ฃน์ ๋ธ๋ก์ ๋ชจ๋ ์ ๊ฑฐ. $B^2$์ ์ ํ๋(B → ๋ธ๋ก์ ๊ฐ์)
- ์ค๋ ฅ ์์ฉ ๐ ๊ฒ์์ ๋ธ๋ก์ ์ ์ธํ ๋ชจ๋ ๋ธ๋ก์ด ํ์ ๋ฒํธ๊ฐ ํฐ ์นธ์ผ๋ก ์ด๋, ๋ค๋ฅธ ๋ธ๋ก์ด๋ ๊ฒฉ์์ ๊ฒฝ๊ณ๋ฅผ ๋ง๋๊ธฐ ์ ๊น์ง
- ๊ฒฉ์๊ฐ 90๋ ๋ฐ์๊ณ ๋ฐฉํฅ์ผ๋ก ํ์
- ์ค๋ ฅ ์์ฉ
๋ฌธ์ ํ์ด
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;
}
}
}
}
}
'์๊ณ ๋ฆฌ์ฆ > ๋ฐฑ์ค' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[ BOJ / ๋ฐฑ์ค 5212 ] ์ง๊ตฌ ์จ๋ํ ( ์๋ฐ / JAVA ) (0) | 2022.02.15 |
---|---|
[ ๋ฐฑ์ค / BOJ 20436 ] ZOAC 3 ( JAVA / ์๋ฐ ) (0) | 2022.02.15 |
[ BOJ / ๋ฐฑ์ค 20061 ] ๋ชจ๋ ธ๋ฏธ๋ ธ๋๋ฏธ๋ ธ 2 ( ์๋ฐ / JAVA ) (0) | 2022.02.12 |
[ BOJ / ๋ฐฑ์ค 17143 ] ๋์์ ( ์๋ฐ / JAVA ) (0) | 2022.02.09 |
[ ๋ฐฑ์ค / BOJ 19236 ] ์ฒญ์๋ ์์ด ( ์๋ฐ / JAVA ) (0) | 2022.02.08 |