반응형

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

 

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

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

www.acmicpc.net

 

 

[ 문제풀이 ]

 

1. 구역을 나눕니다.

 

2. 나눈 구역을 temp 배열에 넣어 90도 회전해줍니다.

 

3. 회전시킨 temp 배열을 arr 배열에 갱신해줍니다.

 

4. 갱신된 arr배열을 바탕으로 temp 배열에 얼음의 양을 갱신해줍니다.

 

5. temp배열을 arr배열에 옮겨 주고 위를 반복합니다.

 

6. 위 과정이 끝나면 arr배열을 바탕으로 ans에 얼음의 양을 저장하고, bfs를 돌려 덩어리의 크기를 Max에 저장합니다.

 

[ 소스코드 ]

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
#include<iostream>
#include<cmath>
#include<queue>
 
using namespace std;
 
int N, Q;
int arr[64][64];
int temp[64][64];
int dy[4= { -1,1,0,0 };
int dx[4= { 0,0,-1,1 };
 
int bfs(int y, int x)    //덩어리 크기
{
    queue<pair<intint>> q;
    q.push({ y,x });
 
    temp[y][x] = 0;
    int cnt = 1;
 
    while (!q.empty())
    {
        int y = q.front().first;
        int x = q.front().second;
        q.pop();
 
        for (int i = 0; i < 4; i++) {
            int yy = y + dy[i];
            int xx = x + dx[i];
            if(yy >= 0 && yy < N&& xx >= 0 && xx < N) {
                if (temp[yy][xx] > 0) {
                    temp[yy][xx] = 0;
                    q.push({ yy,xx });
                    cnt++;
                }
            }
        }
    }
 
    return cnt;
}
 
bool check(int y, int x)    //얼음이 주변에 3개 이상 있는지
{
    int cnt = 0;
 
    for (int i = 0; i < 4; i++) {
        int yy = y + dy[i];
        int xx = x + dx[i];
 
        if (yy >= 0 && yy < N && xx >= 0 && xx < N) {
            if (arr[yy][xx] > 0) {
                cnt++;
            }
        }
    }
 
    if (cnt >= 3) {
        return true;
    }
    else {
        return false;
    }
}
 
void firestorm()    //파이어스톰 적용
{
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            if (arr[i][j] > 0) {
                if (!check(i, j)) {
                    temp[i][j] = arr[i][j] - 1;
                }
                else {
                    temp[i][j] = arr[i][j];
                }
            }
            else {
                temp[i][j] = 0;
            }
        }
    }
 
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            arr[i][j] = temp[i][j];
        }
    }
}
 
void turn(int y, int x, int L)    //90도 회전
{
    for (int i = 0; i < L; i++) {
        for (int j = 0; j < L; j++) {
            temp[i][j] = arr[y + i][x + j];
        }
    }
 
    for (int i = 0; i < L; i++) {
        for (int j = 0; j < L; j++) {
            arr[y + i][x + L - j - 1= temp[j][i];
        }
    }
}
 
void devide(int L)    //구역 나누기
{
    for (int i = 0; i < N; i += L) {
        for (int j = 0; j < N; j += L) {
            turn(i, j, L);
        }
    }
}
 
int main()
{
    scanf("%d %d"&N, &Q);
 
    N = pow(2, N);
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            scanf("%d"&arr[i][j]);
        }
    }
 
    for (int i = 0; i < Q; i++) {
        int L;
        scanf("%d"&L);
        L = pow(2, L);
        devide(L);
 
        firestorm();
    }
 
    int ans = 0;
    int Max = 0;
 
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            ans += arr[i][j];
            if (temp[i][j] > 0) {
                int cnt = bfs(i, j);
                Max = max(cnt, Max);
            }
        }
    }
 
    printf("%d\n%d", ans, Max);
}
 
cs
반응형

+ Recent posts