Game Develop

[Algorithm] Baekjoon 20058번 : 마법사 상어와 파이어스톰 본문

Algorithm/Baekjoon

[Algorithm] Baekjoon 20058번 : 마법사 상어와 파이어스톰

MaxLevel 2023. 9. 7. 22:09

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

 

20058번: 마법사 상어와 파이어스톰

마법사 상어는 파이어볼과 토네이도를 조합해 파이어스톰을 시전할 수 있다. 오늘은 파이어스톰을 크기가 2N × 2N인 격자로 나누어진 얼음판에서 연습하려고 한다. 위치 (r, c)는 격자의 r행 c

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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
using namespace std;
 
int n, q;
int arr[64][64= { 0 };
int temp[64][64= { 0 };
int lSize[1001= { 0 };
int dir[4][2= { {-1,0}, {1,0}, {0,-1}, {0,1} };
 
int sumIce = 0;
int maxSize = 0;
bool visited[64][64= { false };
 
void rotate(int startY, int startX, int l)
{
    int size = pow(2, l);
 
    for (int i = 0; i < size++i)
    {
        for (int j = 0; j < size++j)
        {
            temp[j][size - i - 1= arr[i + startY][j + startX];
        }
    }
 
    for (int i = 0; i < size++i)
    {
        for (int j = 0; j < size++j)
        {
            arr[i + startY][j + startX] = temp[i][j];
        }
    }
}
 
void melt()
{
    memcpy(temp, arr, sizeof(temp));
 
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            if (temp[i][j] == 0continue;
 
            int count = 0;
 
            for (int d = 0; d < 4++d)
            {
                int nextY = i + dir[d][0];
                int nextX = j + dir[d][1];
 
                if (nextY < 0 || nextY >= n) continue;
                if (nextX < 0 || nextX >= n) continue;
 
                if (temp[nextY][nextX] >= 1++count;
            }
 
            if (count < 3) arr[i][j] = max(0--arr[i][j]);
        }
    }
}
 
void GetSumIce()
{
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            sumIce += arr[i][j];
        }
    }
}
 
struct Node
{
    int y;
    int x;
};
 
void GetMaxSize(int startY, int startX)
{
    int count = 0;
 
    queue<Node> q;
    q.push({ startY,startX });
    ++count;
 
    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 >= n) continue;
            if (nextX < 0 || nextX >= n) continue;
            if (visited[nextY][nextX]) continue;
            if (arr[nextY][nextX] == 0continue;
 
            visited[nextY][nextX] = true;
            q.push({ nextY,nextX });
            ++count;
        }
    }
 
    maxSize = max(maxSize, count);
}
 
int main(void)
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
 
    cin >> n >> q;
 
    n = pow(2, n);
 
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            cin >> arr[i][j];
        }
    }
 
    for (int i = 0; i < q; ++i)
    {
        cin >> lSize[i];
 
        int size = pow(2, lSize[i]);
 
        for (int r = 0; r < n; r += size)
        {
            for (int c = 0; c < n; c += size)
            {
                rotate(r, c, lSize[i]);
            }
        }
 
        melt();
    }
 
    GetSumIce();
 
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            if (visited[i][j]) continue;
            if (arr[i][j] == 0continue;
 
            visited[i][j] = true;
            GetMaxSize(i, j);
        }
    }
 
    cout << sumIce << endl << maxSize;
}
cs

 

행렬회전하는 코드 말고는 일방적인 구현문제이다.

다만 유의할 점은, 얼음을 녹일 때 반드시 원본기준으로 녹여야한다는것을 잊으면 안된다.

이전에 녹인게 다음거에 영향을 줘서는 안된다.

 

행렬회전코드같은 경우는, 원본의 회전시킬 범위내의 코드를 temp의 0부터 시작하는 같은범위로 회전시켜서 복사한다. 

이후 전부 회전복사 후, 다시 원본의 범위로 그대로 복사했다.