https://www.acmicpc.net/problem/11559
11559번: Puyo Puyo
총 12개의 줄에 필드의 정보가 주어지며, 각 줄에는 6개의 문자가 있다. 이때 .은 빈공간이고 .이 아닌것은 각각의 색깔의 뿌요를 나타낸다. R은 빨강, G는 초록, B는 파랑, P는 보라, Y는 노랑이다.
www.acmicpc.net
코드설명
Simulation(시뮬레이션) + BFS(너비우선탐색)을 활용합니다.
코드로직입니다.
- simulate 메서드: 시뮬레이션하는 메서드로, 각 턴마다 그룹핑하고, 그룹마다의 개수를 셈으로써 게임을 진행합니다. 또한 4개 이상의 퍼즐이 모여있는 그룹이 있다면 삭제 작업을 진행합니다.
- groupBFS 메서드: BFS 알고리즘을 사용하여 그룹을 형성하는 메서드입니다. 각 그룹의 개수와 해당 그룹의 인덱스를 저장하며, 이 정보를 활용하여 나중에 폭파할 때 활용합니다.
- bombBFS 메서드: BFS 알고리즘을 사용하여 4개 이상이 모인 그룹의 퍼즐을 폭파시키고, 테트리스처럼 아래로 내려주는 작업을 수행합니다.
문제에서 폭파 후 테트리스처럼 내려주는 로직을 만들때, 각 열을 맨 아래 행에서부터 올라가며 최대한 내릴 수 있도록 내림처리합니다. 또한 내린 이후에는 내린칸은 빈칸으로 바꿔줍니다.
//모두 지웠다면, 이제 내려줘야한다.
for(int j=0; j<6;j++) {
for(int i=11; i>=0; i--) {
if(map[i][j] != '.') {
int startRow = i;
while(startRow < 11) {
if( map[startRow + 1][j] == '.' ) {
startRow += 1;
}else {
break;
}
}
if(startRow > i) {
map[startRow][j] = map[i][j];
map[i][j] = '.';
}
}
}
}
처음에 시간초과가 발생할까봐 걱정했는데, 항상 테이블이 12x6 으로 고정되어있으므로 걱정할 필요가 없습니다.
코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
public class Main {
public static int N, M, K;
public static int[] arr;
public static char[][] map;
public static int answer = 0;
public static int groupIdx = 0;
public static int[][] groupMap;
public static int[][] groupCnt;
public static int[] dx = {-1,1,0,0};
public static int[] dy = {0,0,-1,1};
public static int maxCnt = 0;
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
map = new char[12][6];
for(int i=0;i<12;i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
map[i] = st.nextToken().toCharArray();
}
groupMap = new int[12][6];
groupCnt = new int[12][6];
groupIdx = 0;
simulate();
System.out.println(answer - 1);
}
public static void simulate() {
//각 턴
answer = 0;
while(true) {
answer += 1;
//그룹핑하고, 각 그룹마다의 개수를 모두 셌습니다.
//또한 만약 4개를 폭파시킬경우에만 지속합니다.
groupBFS();
//각 그룹의 개수가 4개 이상인 그룹이 있다면, 삭제 작업을 진행합니다.
if( bombBFS() == false) {
break;
}
}
}
public static boolean bombBFS() {
Queue<Node> q = new LinkedList<>();
boolean flag = false;
for(int i=0;i<12;i++) {
for(int j=0;j<6;j++) {
//만약 4보다 크거나 같다면,
if(groupCnt[i][j] >= 4 && map[i][j] != '.') {
int storeGroupIdx = groupMap[i][j];
map[i][j] = '.';
groupCnt[i][j] = 0;
q.offer(new Node(i, j, 0));
while(!q.isEmpty()) {
Node temp = q.poll();
for(int dir = 0; dir < 4; dir++) {
int nr = temp.r + dx[dir];
int nc = temp.c + dy[dir];
if(nr < 0 || nr >= 12 || nc < 0 || nc >= 6) continue;
if(groupMap[nr][nc] != storeGroupIdx) continue;
if(groupCnt[nr][nc] == 0) continue;
groupCnt[nr][nc] = 0;
map[nr][nc] = '.';
q.offer(new Node(nr, nc, temp.cnt + 1));
flag = true;
}
}
}
}
}
//모두 지웠다면, 이제 내려줘야한다.
for(int j=0; j<6;j++) {
for(int i=11; i>=0; i--) {
if(map[i][j] != '.') {
int startRow = i;
while(startRow < 11) {
if( map[startRow + 1][j] == '.' ) {
startRow += 1;
}else {
break;
}
}
if(startRow > i) {
map[startRow][j] = map[i][j];
map[i][j] = '.';
}
}
}
}
return flag;
}
public static void groupBFS() {
Queue<Node> storeQ = new LinkedList<>();
groupIdx = 1;
maxCnt = 0;
groupMap = new int[12][6];
groupCnt = new int[12][6];
for(int i=0;i<12;i++) {
for(int j=0;j<6;j++) {
if(groupMap[i][j] == 0) {
maxCnt = 0;
Queue<Node> q = new LinkedList<>();
q.offer(new Node(i, j, 0));
storeQ.offer(new Node(i, j, 0));
groupMap[i][j] = groupIdx;
maxCnt += 1;
char puyo = map[i][j];
while(!q.isEmpty()) {
Node temp = q.poll();
for(int dir = 0; dir<4; dir++) {
int nr = temp.r + dx[dir];
int nc = temp.c + dy[dir];
if(nr < 0 || nr >= 12 || nc < 0 || nc >= 6) continue;
if(groupMap[nr][nc] != 0) continue;
if(map[nr][nc] != puyo) continue;
groupMap[nr][nc] = groupIdx;
maxCnt += 1;
q.offer(new Node(nr, nc, temp.cnt + 1));
storeQ.offer(new Node(nr, nc, temp.cnt + 1));
}
}
groupIdx += 1;
while(!storeQ.isEmpty()) {
Node temp = storeQ.poll();
groupCnt[temp.r][temp.c] = maxCnt;
}
}
}
}
}
}
class Node{
int r;
int c;
int cnt;
public Node(int r, int c, int cnt) {
this.r = r;
this.c = c;
this.cnt = cnt;
}
}
'알고리즘 > 백준' 카테고리의 다른 글
[백준] 15898 피아의 아틀리에 ~신비한 대회의 연금술사~ - Simulation(시뮬레이션) + Normal Permutation (일반순열) + Brute Force(완전탐색) JAVA (0) | 2023.12.21 |
---|---|
[백준] 16986 인싸들의 가위바위보 - Simulation(시뮬레이션) + Normal Permutation (일반순열) JAVA (0) | 2023.12.20 |
[백준] 15655 N과 M (6) - 백트래킹(BackTracking) JAVA (0) | 2023.12.19 |
[백준] 4883 삼각 그래프 - 동적계획법(DP, Dynamic Programming) JAVA (0) | 2023.12.18 |
[백준] 11967 불켜기 - BFS(너비우선탐색) JAVA (0) | 2023.12.17 |