Game Develop

[Algorithm] Baekjoon 11559번 : Puyo Puyo 본문

Algorithm/Baekjoon

[Algorithm] Baekjoon 11559번 : Puyo Puyo

MaxLevel 2023. 5. 20. 01:35

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

 

11559번: Puyo Puyo

총 12개의 줄에 필드의 정보가 주어지며, 각 줄에는 6개의 문자가 있다. 이때 .은 빈공간이고 .이 아닌것은 각각의 색깔의 뿌요를 나타낸다. R은 빨강, G는 초록, B는 파랑, P는 보라, Y는 노랑이다.

www.acmicpc.net

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
123
124
125
126
127
128
129
130
131
132
133
134
struct Node
{
    int y;
    int x;
                                                                                                                                                                                                                                                                                                       };
 
char arr[12][6];
Node nodes[12][6];
bool visited[12][6= { false };
int dir[4][2= { {-1,0}, {1,0}, {0,-1}, {0,1} };
int answer = 0;
 
void Update() // 터진 후 빈자리에 매꾸기.
{
    for (int i = 0; i < 6++i)
    {
        int count = 0;
        int row = 11;
 
        while (row >= 0)
        {
            if (arr[row][i] == '.')
            {
                ++count;
            }
            else
            {
                char temp = arr[row + count][i];
                arr[row + count][i] = arr[row][i];
                arr[row][i] = temp;
            }
 
            --row;
        }
    }
}
 
bool TryBomb(int y, int x, char standard) // 4개이상이여서 터지면 true 리턴.
{
    visited[y][x] = true;
    queue<Node> q;
    q.push({ y,x });
    arr[y][x] = '.';
    int count = 1;
    vector<Node> temp;
    temp.push_back({ y,x });
 
    while (!q.empty())
    {
        int curY = q.front().y;
        int curX = q.front().x;
        q.pop();
 
        for (int i = 0; i < 4++i)
        {
            int nextY = curY + dir[i][0];
            int nextX = curX + dir[i][1];
 
            if (nextY < 0 || nextY >= 12continue;
            if (nextX < 0 || nextX >= 6continue;
            if (visited[nextY][nextX]) continue;
            if (arr[nextY][nextX] != standard) continue;
 
            ++count;
            temp.push_back({ nextY,nextX });
            visited[nextY][nextX] = true;
            arr[nextY][nextX] = '.';
            q.push({ nextY,nextX });
        }
    }
 
    if (count < 4)
    {
        for (int i = 0; i < temp.size(); ++i)
        {
            arr[temp[i].y][temp[i].x] = standard;
        }
        return false;
    }
    
    return true;
}
 
 
bool Check()
{
    int count = 0;
    memset(visited, falsesizeof(visited));
 
    for (int i = 0; i < 12++i)
    {
        for (int j = 0; j < 6++j)
        {
            if (arr[i][j] != '.' && !visited[i][j])
            {
                bool check = TryBomb(i, j, arr[i][j]);
                
                if (check) ++count;
            }
        }
    }
 
    // 한번이라도 터졌으면 true 리턴. 터진게 하나도 없으면 false리턴.
    if (count >= 1return true;
    else return false;
}
 
int main(void)
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
 
    for (int i = 0; i < 12++i)
    {
        for (int j = 0; j < 6++j)
        {
            cin >> arr[i][j];
        }
    }
 
    while (1)
    {
        if (Check()) // 터졌으면
        {
            ++answer;
            Update();
        }
        else break;
    }
 
    cout << answer;
 
    return 0;
}
cs

어렵지않은 BFS 구현문제이다. 

arr에서 터질 조건을 갖춘(4개이상 연결된) 뿌요들을 전부 동시에 터트린 후, 만약 한덩어리라도 터진 뿌요가 있다면 빈공간에 대해 메꿔야하니 메꾸는 로직을 수행해준다. 메꾸는 로직은 그냥 각 arr의 바닥부터 제일 위까지 검사하면서, '.'이면 카운팅해주다가 뿌요를 만나면 카운팅해준 빈공간만큼 행위치로 자리를 바꿔줬다.

 

로직을 수행하다 단 하나의 뿌요덩어리가 터지지 않았다면 실행을 중단하고 연쇄값을 출력한다.