โจ ๊ตฌํ & BFS
https://www.acmicpc.net/problem/21609
21609๋ฒ: ์์ด ์คํ๊ต
์์ด ์คํ๊ต์ ์ฝ๋ฉ ๋์๋ฆฌ์์ ๊ฒ์์ ๋ง๋ค์๋ค. ์ด ๊ฒ์์ ํฌ๊ธฐ๊ฐ N×N์ธ ๊ฒฉ์์์ ์งํ๋๊ณ , ์ด๊ธฐ์ ๊ฒฉ์์ ๋ชจ๋ ์นธ์๋ ๋ธ๋ก์ด ํ๋์ฉ ๋ค์ด์๊ณ , ๋ธ๋ก์ ๊ฒ์์ ๋ธ๋ก, ๋ฌด์ง๊ฐ ๋ธ๋ก, ์ผ๋ฐ ๋ธ๋ก
www.acmicpc.net
๐ ๊ณ ๋ คํด์ผํ ์
- ๊ทธ๋ฃน์ ์ํ๋ ๋ธ๋ก์ ์กฐ๊ฑด
- ์ผ๋ฐ ๋ธ๋ก์ด ์ ์ด๋ ํ๋ ์ด์
- ์ผ๋ฐ ๋ธ๋ก์ ์์ ๋ชจ๋ ๊ฐ์์ผํจ
- ๊ฒ์์ ๋ธ๋ก ํฌํจ X
- ๋ฌด์ง๊ฐ์ ๋ธ๋ก์ ๋ช๊ฐ๋ ์๊ด X
- ๋ธ๋ก์ ๊ฐ์๋ 2๊ฐ ์ด์
- ๋ธ๋ก ๊ทธ๋ฃน์ ๊ธฐ์ค ๋ธ๋ก = ๋ฌด์ง๊ฐ ๋ธ๋ก์ด ์๋ ๋ธ๋ก ์ค์์ ํ์ ๋ฒํธ๊ฐ ๊ฐ์ฅ ์์ ๋ธ๋ก. ๊ทธ๋ฌํ ๋ธ๋ก์ด ์ฌ๋ฌ ๊ฐ์ด๋ฉด ์ด์ ๋ฒํธ๊ฐ ๊ฐ์ฅ ์์ ๋ธ๋ก ..
- ์คํ ํ๋ ์ด ๊ธฐ๋ฅ โ ๋ธ๋ก ๊ทธ๋ฃน์ด ์์ ๋๊น์ง ๋ฐ๋ณต
- ํฌ๊ธฐ๊ฐ ๊ฐ์ฅ ํฐ ๋ธ๋ก ๊ทธ๋ฃน ์ฐพ๊ธฐ
โ ๊ทธ๋ฌํ ๋ธ๋ก ๊ทธ๋ฃน์ด ์ฌ๋ฌ ๊ฐ๋ฉด ๋ธ๋ก ๊ทธ๋ฃน์์ ๋ฌด์ง๊ฐ ๋ธ๋ก์ด ๊ฐ์ฅ ๋ง์ ๋ธ๋ก ๊ทธ๋ฃน ์ ํ
โ ๊ทธ๋ฌํ ๋ธ๋ก ๊ทธ๋ฃน๋ ์ฌ๋ฌ ๊ฐ๋ฉด ๊ธฐ์ค ๋ธ๋ก์ ํ์ด ๊ฐ์ฅ ํฐ ๊ฒ ์ ํ
โ ๊ทธ๋ฌํ ๋ธ๋ก ๊ทธ๋ฃน ๋ํ ์ฌ๋ฌ ๊ฐ๋ฉด ์ด์ด ๊ฐ์ฅ ํฐ ๊ฒ ์ ํ - 1๋ฒ์์ ์ฐพ์ ๋ธ๋ก ๊ทธ๋ฃน์ ๋ชจ๋ ๋ธ๋ก ์ ๊ฑฐํ๊ณ , ๋ธ๋ก ๊ทธ๋ฃน์ ํฌํจ๋ ๋ธ๋ก์ ์=B๋ผ ํ ๋, B์ ์ ๊ณฑ๋งํผ ์ ์ ํ๋
- ๊ฒฉ์์ ์ค๋ ฅ ์์ฉ โ ๊ฒ์์ ๋ธ๋ก์ ์ ์ธํ ๋ชจ๋ ๋ธ๋ก์ด ํ์ ๋ฒํธ๊ฐ ํฐ ์นธ์ผ๋ก ๋ค๋ฅธ ๋ธ๋ก์ด๋ ๊ฒฉ์์ ๊ฒฝ๊ณ๋ฅผ ๋ง๋ ๋๊น์ง ์ด๋
- ๊ฒฉ์๋ฅผ 90๋ ๋ฐ์๊ณ๋ฐฉํฅ ํ์ ์ํค๊ธฐ
- ๋ค์ ๊ฒฉ์์ ์ค๋ ฅ ์์ฉ
- ํฌ๊ธฐ๊ฐ ๊ฐ์ฅ ํฐ ๋ธ๋ก ๊ทธ๋ฃน ์ฐพ๊ธฐ
๐ ๊ณ ๋ คํด์ผํ ์กฐ๊ฑด๋ค์ด ๋ง๋ค...
๐น๏ธ ํ์ด ๊ณผ์
findBlockGroup()
โ ๋ธ๋ก ๊ทธ๋ฃน ์ฐพ๋ ๋ฉ์๋bfs()
โ ๋ธ๋ก ๊ทธ๋ฃน ์ฐพ๋ ๋ฉ์๋gravity()
โ ์ค๋ ฅ ์์ฉํ๋ ๋ฉ์๋rotate()
โ ๊ฒฉ์๋ฅผ 90๋ ๋ฐ์๊ณ๋ฐฉํฅ์ผ๋ก ํ์ remove()
โ ๋ธ๋ก ๊ทธ๋ฃน์ ๋ธ๋ก๋ค์ ์ ๊ฑฐํ๋ ๋ฉ์๋
๐ 4~5๊ฐ์ ๋ฉ์๋๋ก ์์ฑํ ์ ์๋ค.
์ฐ์ , ์ขํ์ ๋ํ ์ ๋ณด์ ๋ธ๋ก ๊ทธ๋ฃน์ ๋ํ ์ ๋ณด๋ฅผ ๋ฐ๋ก ๋ด์ ์ ์๋ ํด๋์ค๋ฅผ ๊ฐ๊ฐ ๋ง๋ค ๊ฒ์ด๋ค.
๐ธ Group : ๋ธ๋ก๊ทธ๋ฃน์ ์ ๋ณด
static class Group implements Comparable<Group> {
int x, y, totalCnt, rainbowCnt;
public Group(int x, int y, int totalCnt, int rainbowCnt) {
this.x=x;
this.y=y;
this.totalCnt=totalCnt;
this.rainbowCnt=rainbowCnt;
}
// ๋ฌด์ง๊ฐ๋ธ๋ก ๊ฐ์ & ํ & ์ด --> ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌ
@Override
public int compareTo(Group o) {
if(totalCnt==o.totalCnt) {
if (rainbowCnt == o.rainbowCnt) {
if (x == o.x) {
return o.y - y;
} return o.x - x;
}return o.rainbowCnt-rainbowCnt;
}return o.totalCnt-totalCnt;
}
}
compareTo() ๋ฉ์๋์ ์คํ ํ๋ ์ด ๊ธฐ๋ฅ #1์ ์กฐ๊ฑด๋ค(๋ธ๋ก ๊ทธ๋ฃน ์ ํ ์กฐ๊ฑด)์ ์์ฑํด์ค ๊ฒ์ด๋ค.
๐ธ Info : ์ขํ ์ ๋ณด
static class Info{
int x, y;
public Info(int x, int y) {
this.x=x;
this.y=y;
}
}
๋ณดํต ๋ฐฐ์ด์ ์ฌ์ฉํด์ arr[0]์ ํ์ ๊ฐ์, arr[1]์ ์ด์ ๊ฐ์ ๋ฃ์ด ์ฌ์ฉํ๊ธฐ๋ ํ์ง๋ง
๊ฐ์ธ์ ์ผ๋ก ๋๋ ํด๋์ค๋ฅผ ๋ฐ๋ก ์ ์ํด์ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ํธ๋ฆฌํ๋ค๊ณ ๋๊ปด ์ขํ ์ ๋ณด ํด๋์ค๋ ์์ฑํ๋ค.
๐นfindBlockGroup() : ๋ธ๋ก ๊ทธ๋ฃน ์ฐพ๊ธฐ
static boolean findBlockGroup(){
visit = new boolean[N][N];
list = new ArrayList<>(); // Group์ ๋ด์ ๋ฆฌ์คํธ
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (!visit[i][j] && board[i][j] > 0) {
bfs(i, j, true);
}
}
}
visit = new boolean[N][N]; // ๋ธ๋ก๊ทธ๋ฃน์ ์ํ ๋ธ๋ก๋ค์ ์ฐพ์์ผํ๊ธฐ ๋๋ฌธ์ ๋ค์ ์ด๊ธฐํ์ํจ๋ค.
if(list.isEmpty()) return false; // ๋ธ๋ก๊ทธ๋ฃน์ ๋ง๋ค ์ ์๋ค๋ฉด false ๋ฐํ
else{
Collections.sort(list); // Group์ compareTo์ ๋ฐ๋ผ ์ ๋ ฌ๋จ.
bfs(list.get(0).x,list.get(0).y, false);
remove();
}
return true;
}
๐น bfs() : ๋ธ๋ก ๊ทธ๋ฃน ๋ณธ๊ฒฉ์ ์ผ๋ก ์ฐพ๊ธฐ
public static void bfs(int x, int y, boolean flag){
int rainbow = 0;
int cntBlock = 1;
Queue<Info> queue = new LinkedList<>();
queue.add(new Info(x, y));
visit[x][y] = true;
while (!queue.isEmpty()) {
Info now = queue.poll();
for (int i = 0; i < 4; i++) {
int nx = now.x + dx[i];
int ny = now.y + dy[i];
if (nx >= 0 && ny >= 0 && nx < N && ny < N && !visit[nx][ny]) {
// ๋ธ๋ก ๊ทธ๋ฃน์ ์์ด ๊ฐ๊ฑฐ๋ ๋ฌด์ง๊ฐ์์ด๋ฉด ใ
ใ
if(board[nx][ny]==0 || board[nx][ny]==board[x][y]){
visit[nx][ny] = true;
if(board[nx][ny]==0) rainbow++;
queue.add(new Info(nx, ny));
cntBlock++;
}
}
}
// ๋ธ๋ก๊ทธ๋ฃน์ ๋ธ๋ก ๊ฐ์๊ฐ 2๊ฐ ์ด์์ด๋ผ๋ฉด ใ
ใ
// ๋ฌด์ง๊ฐ ๋ธ๋ก์ด ์๋ ๋ธ๋ก ์ค์์ ํ์ ๋ฒํธ๊ฐ ๊ฐ์ฅ ์์ ๋ธ๋ก, ์ด์ ๋ฒํธ๊ฐ ๊ฐ์ฅ ์์ ๋ธ๋ก
// -> ์์ฐจ์ ์ผ๋ก ํ์ํ๊ธฐ ๋๋ฌธ์ ๋ฐ๋ก ๊ณ ๋ คํ์ง ์์๋ ๋จ
if(cntBlock>=2) list.add(new Group(x, y, cntBlock, rainbow));
// flag๊ฐ false๋ผ๋ฉด ๋ธ๋ก์ ์ ๊ฑฐํ ๋จ๊ณ๋ฅผ ๊ฑฐ์น ๊ฒ์.
// flag๊ฐ true๋ผ๋ฉด ๋ธ๋ก๊ทธ๋ฃน์ ํ์ํ๋ ๋จ๊ณ๋ฅผ ๊ฑฐ์น ๊ฒ์
// -> ๋ฌด์ง๊ฐ์์ธ ๋ธ๋ก์ ๋ค๋ฅธ ๋ธ๋ก๊ทธ๋ฃน์ ๋ ์ํ ์๋ ์๊ธฐ ๋๋ฌธ์ ์ฌ๋ฐฉ๋ฌธ ๊ฐ๋ฅํ๋๋ก visit์ false๋ก ๋๋๋ฆฐ๋ค.
if(flag){
for(int i=0; i<N; i++){
for(int j=0; j<N; j++){
if(board[i][j]==0) visit[i][j]=false;
}
}
}
}
}
๐น remove() : ์ ํ๋ ๋ธ๋ก๊ทธ๋ฃน์ ๋ธ๋ก๋ค ์ ๊ฑฐํ๊ธฐ
๋ธ๋ก๋ค์ ๊ฐ์์ ์ ๊ณฑ๋งํผ ์ ์์ ๋ํ๋ค.
public static void remove(){
int cnt=0;
for(int i=0; i<N; i++){
for(int j=0; j<N; j++){
if(visit[i][j]){
cnt++;
board[i][j] = -2; // -2๋ก ๋น์นธ์ ํ์
}
}
}
score+=(cnt*cnt);
}
๐น rotate() : ๊ฒฉ์๋ฅผ ๋ฐ์๊ณ๋ฐฉํฅ์ผ๋ก 90๋ ํ์ ์ํค๊ธฐ
๊ฒฉ์๋ฅผ ๋ฐ์๊ณ๋ฐฉํฅ์ผ๋ก 90๋ ํ์ ์ํค๋ฉด ์์ ๊ทธ๋ฆผ๊ณผ ๊ฐ๋ค.
๊ท์น์ ์ฐพ์๋ณด๋ฉด,
(0, 0) โ (3, 0)
(0, 1) โ (2, 0)
(0, 2) โ (1, 0)
(0, 3) โ (0, 0)
(1, 0) โ (3, 1)
(2, 0) โ (3, 2)
(3, 0) โ (3, 3) ...
์ผ์ชฝ์ด ํ์ ์ํค๊ธฐ ์ ์ ์ขํ์ด๊ณ , ์ค๋ฅธ์ชฝ์ด ํ์ ์ํจ ํ์ ์ขํ์ด๋ค.
(i, j) โ (ni, nj)๋ผ ํ ๋, nj=i
์ด๊ณ , ni = (N-1)-j
์ด๋ค. (N์ ๊ฒฉ์์ ๊ฐ๋ก, ์ธ๋ก ํฌ๊ธฐ)
public static void rotate(){
int[][] tmp = new int[N][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
tmp[(N-1)-j][i] = board[i][j];
}
}
board = tmp;
}
๐น gravity() : ์ค๋ ฅ ์์ฉํ๊ธฐ
์ค๋ ฅ์ด ์์ฉํ๋ฉด ์์ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ด ๋ธ๋ก๋ค์ด ์ด๋ํ๋ค.
๋ฐ์ผ๋ก ์ญ ๋ด๋ ค๋ณด๋ธ๋ค๊ณ ์๊ฐํ๋ฉด ๋๋ค.
static void gravity(){
for (int i = N-1; i >=0; i--) {
for (int j = 0; j < N; j++) {
if (board[i][j]>=0) {
int ni=i;
while (true) {
ni++;
if (ni>=N || board[ni][j] != -2) break;
}
ni--;
if(ni!=i){
board[ni][j] = board[i][j];
board[i][j]=-2;
}
}
}
}
}
๐ฉ๐ป ์ ์ฒด ์ฝ๋
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;
public class BOJ_21609_์์ด์คํ๊ต {
static int N, M, score;
static int[][] board;
static boolean[][] visit;
static int[] dx = {0, 0, 1, -1};
static int[] dy = {1, -1, 0, 0};
static List<Group> list = new ArrayList<>();
static class Group implements Comparable<Group> {
int x, y, totalCnt, rainbowCnt;
public Group(int x, int y, int totalCnt, int rainbowCnt) {
this.x=x;
this.y=y;
this.totalCnt=totalCnt;
this.rainbowCnt=rainbowCnt;
}
// ๋ฌด์ง๊ฐ๋ธ๋ก ๊ฐ์ & ํ & ์ด --> ๋ด๋ฆผ์ฐจ์ ์ ๋ ฌ
@Override
public int compareTo(Group o) {
if(totalCnt==o.totalCnt) {
if (rainbowCnt == o.rainbowCnt) {
if (x == o.x) {
return o.y - y;
} return o.x - x;
}return o.rainbowCnt-rainbowCnt;
}return o.totalCnt-totalCnt;
}
}
static class Info{
int x, y;
public Info(int x, int y) {
this.x=x;
this.y=y;
}
}
static boolean findBlockGroup(){
visit = new boolean[N][N];
list = new ArrayList<>(); // Group์ ๋ด์ ๋ฆฌ์คํธ
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (!visit[i][j] && board[i][j] > 0) {
bfs(i, j, true);
}
}
}
visit = new boolean[N][N]; // ๋ธ๋ก๊ทธ๋ฃน์ ์ํ ๋ธ๋ก๋ค์ ์ฐพ์์ผํ๊ธฐ ๋๋ฌธ์ ๋ค์ ์ด๊ธฐํ์ํจ๋ค.
if(list.isEmpty()) return false; // ๋ธ๋ก๊ทธ๋ฃน์ ๋ง๋ค ์ ์๋ค๋ฉด false ๋ฐํ
else{
Collections.sort(list); // Group์ compareTo์ ๋ฐ๋ผ ์ ๋ ฌ๋จ.
bfs(list.get(0).x,list.get(0).y, false);
remove();
}
return true;
}
// ** ๋ธ๋ก --> ๊ฒ์ ๋ธ๋ก ํฌํจ X && ์ผ๋ฐ ๋ธ๋ก์ ๋ชจ๋ ๋์ผ (์ ์ด๋ ํ๋ ์ด์) && ๋ฌด์ง๊ฐ ๋ธ๋ก์ ์๊ด X
// #1. ๊ฐ์ฅ ํฐ ๋ธ๋ก ์ฐพ๊ธฐ --> ๋ธ๋ก ๊ฐ์ -> ๋ฌด์ง๊ฐ ๋ธ๋ก ๊ฐ์ -> ๊ธฐ์ค ๋ธ๋ก์ ํ (๊ฐ์ฅ ํผ) -> ๊ธฐ์ค ๋ธ๋ก์ ์ด (๊ฐ์ฅ ํผ)
public static void bfs(int x, int y, boolean flag){
int rainbow = 0;
int cntBlock = 1;
visit[x][y] = true;
Queue<Info> queue = new LinkedList<>();
queue.add(new Info(x, y));
while (!queue.isEmpty()) {
Info now = queue.poll();
for (int i = 0; i < 4; i++) {
int nx = now.x + dx[i];
int ny = now.y + dy[i];
if (nx >= 0 && ny >= 0 && nx < N && ny < N && !visit[nx][ny]) {
// ๋ธ๋ก ๊ทธ๋ฃน์ ์์ด ๊ฐ๊ฑฐ๋ ๋ฌด์ง๊ฐ์์ด๋ฉด ใ
ใ
if(board[nx][ny]==0 || board[nx][ny]==board[x][y]){
visit[nx][ny] = true;
if(board[nx][ny]==0) rainbow++;
queue.add(new Info(nx, ny));
cntBlock++;
}
}
}
}
// ๋ธ๋ก๊ทธ๋ฃน์ ๋ธ๋ก ๊ฐ์๊ฐ 2๊ฐ ์ด์์ด๋ผ๋ฉด ใ
ใ
// ๋ฌด์ง๊ฐ ๋ธ๋ก์ด ์๋ ๋ธ๋ก ์ค์์ ํ์ ๋ฒํธ๊ฐ ๊ฐ์ฅ ์์ ๋ธ๋ก, ์ด์ ๋ฒํธ๊ฐ ๊ฐ์ฅ ์์ ๋ธ๋ก
// -> ์์ฐจ์ ์ผ๋ก ํ์ํ๊ธฐ ๋๋ฌธ์ ๋ฐ๋ก ๊ณ ๋ คํ์ง ์์๋ ๋จ
if(cntBlock>=2) list.add(new Group(x, y, cntBlock, rainbow));
// flag๊ฐ false๋ผ๋ฉด ๋ธ๋ก์ ์ ๊ฑฐํ ๋จ๊ณ๋ฅผ ๊ฑฐ์น ๊ฒ์.
// flag๊ฐ true๋ผ๋ฉด ๋ธ๋ก๊ทธ๋ฃน์ ํ์ํ๋ ๋จ๊ณ๋ฅผ ๊ฑฐ์น ๊ฒ์
// -> ๋ฌด์ง๊ฐ์์ธ ๋ธ๋ก์ ๋ค๋ฅธ ๋ธ๋ก๊ทธ๋ฃน์ ๋ ์ํ ์๋ ์๊ธฐ ๋๋ฌธ์ ์ฌ๋ฐฉ๋ฌธ ๊ฐ๋ฅํ๋๋ก visit์ false๋ก ๋๋๋ฆฐ๋ค.
if(flag){
for(int i=0; i<N; i++){
for(int j=0; j<N; j++){
if(board[i][j]==0) visit[i][j]=false;
}
}
}
}
public static void remove(){
int cnt=0;
for(int i=0; i<N; i++){
for(int j=0; j<N; j++){
if(visit[i][j]){
cnt++;
board[i][j] = -2; // -2๋ก ๋น์นธ์ ํ์
}
}
}
score+=(cnt*cnt);
}
// #3. ์ค๋ ฅ ์์ฉ -> ๊ฒ์์ ๋ธ๋ก์ ์ ์ธํ ๋ชจ๋ ๋ธ๋ก์ด ํ์ ๋ฒํธ๊ฐ ํฐ ์นธ์ผ๋ก ์ด๋
public static void gravity(){
for (int i = N-1; i >=0; i--) {
for (int j = 0; j < N; j++) {
if (board[i][j]>=0) {
int ni=i;
while (true) {
ni++;
if (ni>=N || board[ni][j] != -2) break;
}
ni--;
if(ni!=i){
board[ni][j] = board[i][j];
board[i][j]=-2;
}
}
}
}
}
// #4. 90๋ ๋ฐ์๊ณ๋ฐฉํฅ ํ์
public static void rotate(){
int[][] tmp = new int[N][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
tmp[(N-1)-j][i] = board[i][j];
}
}
board = tmp;
}
public static void main(String[] args) throws Exception {
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][N];
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < N; j++) {
board[i][j] = Integer.parseInt(st.nextToken());
}
}
while(true){
if (!findBlockGroup()) break;
gravity();
rotate();
gravity();
}
System.out.println(score);
}
}
'์๊ณ ๋ฆฌ์ฆ > BOJ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[BOJ] 17485 ์ง์ฐ์ ๋ฌ ์ฌํ (Large) - Java (0) | 2024.03.12 |
---|---|
[BOJ] 20058 ๋ง๋ฒ์ฌ ์์ด์ ํ์ด์ด์คํฐ - Java (0) | 2024.03.01 |
[BOJ] 1018 ์ฒด์คํ ๋ค์ ์น ํ๊ธฐ - Java (0) | 2023.12.05 |
[BOJ] 1504 ํน์ ํ ์ต๋จ ๊ฒฝ๋ก - Java (0) | 2023.12.05 |
[BOJ] 18352 ํน์ ๊ฑฐ๋ฆฌ์ ๋์ ์ฐพ๊ธฐ - Java (0) | 2023.12.04 |