본문 바로가기
알고리즘/코딩 - 백준

[Java][자바][백준][11559번] Puyo Puyo

by 주남2 2019. 11. 20.
반응형

문제 설명

뿌요뿌요의 룰은 다음과 같다.

필드에 여러 가지 색깔의 뿌요를 놓는다. 뿌요는 중력의 영향을 받아 아래에 바닥이나 다른 뿌요가 나올 때까지 아래로 떨어진다.

뿌요를 놓고 난 후, 같은 색 뿌요가 4개 이상 상하좌우로 연결되어 있으면 연결된 같은 색 뿌요들이 한꺼번에 없어진다.

뿌요들이 없어지고 나서 위에 다른 뿌요들이 있다면, 역시 중력의 영향을 받아 차례대로 아래로 떨어지게 된다.

아래로 떨어지고 나서 다시 같은 색의 뿌요들이 4개 이상 모이게 되면 또 터지게 되는데, 터진 후 뿌요들이 내려오고 다시 터짐을 반복할 때마다 1연쇄씩 늘어난다.

터질 수 있는 뿌요가 여러 그룹이 있다면 동시에 터져야 하고 여러 그룹이 터지더라도 한번의 연쇄가 추가된다.

남규는 최근 뿌요뿌요 게임에 푹 빠졌다. 이 게임은 1:1로 붙는 대전게임이라 잘 쌓는 것도 중요하지만, 상대방이 터뜨린다면 연쇄가 몇 번이 될지 바로 파악할 수 있는 능력도 필요하다. 하지만 아직 실력이 부족하여 남규는 자기 필드에만 신경 쓰기 바쁘다. 상대방의 필드가 주어졌을 때, 연쇄가 몇 번 연속으로 일어날지 계산하여 남규를 도와주자!

입력

12*6의 문자가 주어진다.

이때 .은 빈공간이고 .이 아닌것은 각각의 색깔의 뿌요를 나타낸다.

R은 빨강, G는 초록, B는 파랑, P는 보라, Y는 노랑이다.(모두 대문자로 주어진다.)

입력으로 주어지는 필드는 뿌요들이 전부 아래로 떨어진 뒤의 상태(즉 뿌요 아래에 빈 칸이 있는 경우는 없음) 이다.

출력

현재 주어진 상황에서 몇연쇄가 되는지 출력하라. (하나도 터지지 않는다면 0을 출력하면 된다.)

 

생각

주의해야 할 점은 연쇄이다! 더 이상 터질것이 없을 때까지 진행되어야 하므로 참고해야한다.

과정은 다음과 같다.

 

1. 바로 터질 수 있는 뿌요들을 찾는다. (4개 이상 연결되어야 하기 때문에 bfs 나 dfs를 이용하여 갯수를 찾는다.)

2. 한 번에 터트리고 모두 . 으로 변경시킨다.

3. 남은 뿌요들에 대해서 바닥으로 모두 내린다.

4. 1~3번 과정을 반복한다. (더 이상 4개 이상 연결된 뿌요가 없을 때 까지)

 

주석에 자세한 설명을 적도록 하겠다.

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;
 
public class Main {
    static int[] dx = {0,0,-1,1};
    static int[] dy = {1,-1,0,0};
    static int n = 12, m = 6;
    static char[][] map;
    static boolean[][] visited;
    static int crush_count = 0;
    static int total = 0;
    static ArrayList<Integer> result = new ArrayList<Integer>();
    
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        map = new char[n][m];
        
        for(int i=0; i<n; i++) {
            char[] str = br.readLine().toCharArray();
            for(int j=0; j<m; j++) {
                map[i][j] = str[j];
            }
        }
        
        while(true) {
            //매번 마다 새롭게 visited를 초기화 해줘야 한다.
            visited = new boolean[n][m];
            crush_count = 0;
            for(int i=n-1; i>=0; i--) {
                for(int j=m-1; j>=0; j--) {
                    if(map[i][j] != '.' && !visited[i][j]) {
                        bfs(new dot(i,j));
                    }
                }
            }
            //더 이상 터질 것이 없으면 break 한다.
            if(crush_count == 0) {
                break;
            } else {
                total++;
            }
            //남은 뿌요들을 아래로 내리기
            down();
        }
        
        System.out.println(total);
    }
    
    public static void bfs(dot d) {
        char check = map[d.x][d.y];
        int count = 0;
        Queue<dot> q = new LinkedList<dot>();
        ArrayList<dot> save = new ArrayList<dot>();
        visited[d.x][d.y] = true;
        q.add(d);
        
        while(!q.isEmpty()) {
            dot t = q.poll();
            save.add(t);
            count++;
            
            for(int i=0; i<4; i++) {
                int x1 = t.x + dx[i];
                int y1 = t.y + dy[i];
                
                if(x1>=0 && x1<&& y1>=0 && y1<&& map[x1][y1] == check && !visited[x1][y1]) {
                    visited[x1][y1] = true;
                    q.add(new dot(x1,y1));
                }
            }
        }
        //연결된 것이 4개가 넘으면 save의 뿌요들을 .으로 바꾸고 crush_count를 증가시킨다.
        if(count >= 4) {
            crush_count++;
            for(int i=0; i<save.size(); i++) {
                dot tmp = save.get(i);
                map[tmp.x][tmp.y] = '.';
            }
        }
        
    }
    
    //.이 아니라면 goGround함수 실행
    public static void down() {
        for(int i=n-1; i>=0; i--) {
            for(int j=m-1; j>=0; j--) {
                if(map[i][j] != '.') {
                    goGround(i,j);
                }
            }
        }
     }
    //한 열에서 가장 밑에 .이 나오는 인덱스 t를 찾고 원래의 dot(a,b) 와 교환해준다.
    public static void goGround(int a, int b) {
        int t = -1;
        
        for(int i=n-1; i>a; i--) {
            if(map[i][b] == '.') {
                t = i;
                break;
            }
        }
        
        if(t != -1) {
            char tmp = map[a][b];
            map[a][b] = map[t][b];
            map[t][b] = tmp;
        }
    }
}
 
class dot {
    int x;
    int y;
    
    public dot(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
 

bfs, dfs문제는 꾸준히 풀어보는게 정석인 것 같다. 나도 처음엔 코드가 이해가 안가고 어떻게 해야할지 몰랐는데, 10문제 정도 풀고나서 부터는 어떤 방식으로 풀어야할지 감은 잡히기 시작했다.

 

처음부터 잘 되는 사람은 없으므로 이 험난 세상에서 모두모두 화이팅하기 바란다!!

반응형