본문 바로가기
백준

백준 21610 마법사 상어와 비바라기

by 콩순이냉장고 2021. 8. 19.

문제 URL : https://www.acmicpc.net/problem/21610

 

21610번: 마법사 상어와 비바라기

마법사 상어는 파이어볼, 토네이도, 파이어스톰, 물복사버그 마법을 할 수 있다. 오늘 새로 배운 마법은 비바라기이다. 비바라기를 시전하면 하늘에 비구름을 만들 수 있다. 오늘은 비바라기

www.acmicpc.net

문제 접근법 : 예외처리할것도 없고 문제설명이 잘되어있어 말장난 이라고될만한게 설명이 없다시피했네요

하나있다면 설명이 3번 구름을 모두제거한다인데 3번을 미리 제거하게되면 문제설명 4번과 5번을 할수가없으니 4,5번후에 3번을 하시는게 포인트입니다.

그리고 좌표를 (1,1)~(n,n)을 사용하면 나머지연산이 더어려워지니 (0,0)~(n-1,n-1)를 사용합니다.

 

그리고 이동은  경계선 밖으로나가면 다시 반대쪽 경계선으로 들어오도록 if문 사용할필요없이

이동해야할 방향만큼 *s를 곱해서 더한다면 왼쪽이나 위로 이동할때는 음수가 나오는 경우가 있기때문에

n*s만큼더한후 다더해준다음 다시 n으로 나눈 나머지를 하면 됩니다.

 

소스코드 : 

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
//By 콩순이냉장고
#include <bits/stdc++.h>
using namespace std;
#define v vector
#define vi v<int>
#define vvi v<v<int>>
#define pii pair<int,int>
#define vpii v<pii>
int n, m;
vvi board,cloud;
vpii mv;
int dy[8= { 0,-1,-1,-1,0,1,1,1 };
int dx[8= { -1,-1,0,1,1,1,0,-1 };
 
void input(){
    int d, s;
    cin >> n >> m;
    board = vvi(n, vi(n));
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cin >> board[i][j];
        }
    }
 
    for (int i = 0; i < m; i++) {
        cin >> d >> s;
        mv.push_back({ d - 1,s });
    }
}
bool isrange(int y, int x) { return 0 <= y && y < n && 0 <= x && x < n; }
void setcloud(vpii &cv){
    cloud = vvi(n, vi(n));
    for (pii t : cv) 
        cloud[t.first][t.second] = 1;
}
void makecloud(vpii& cv) {
    cv.clear();
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (cloud[i][j]||board[i][j]<2)continue;
            board[i][j] -= 2;
            cv.push_back({ i,j });
        }
    }
}
void solve() {
    vpii cv = { {n - 1,0},{n - 1,1},{n - 2,0},{n - 2,1} };
 
    for (pii move : mv) {
        int d, s;
        vpii temp;
        tie(d, s) = { move.first , move.second };
        
        // 1~2번 모든구름이 d방향으로 s칸 만큼이동후 1증가
        for (int i = 0; i < cv.size(); i++) {
            int ny = (cv[i].first + dy[d] * s + n * s) % n;
            int nx = (cv[i].second + dx[d] * s + n * s) % n;
            temp.push_back({ ny,nx });
            board[ny][nx]++;
        }
        //3번 구름이 모두사라지면4번을 할수가없음 맨나중에해야함
        //4번 구름에있던자리 물복사시전 
        for (int i = 0; i < temp.size(); i++) {
            int cnt = 0;
            for (int j = 1; j < 8; j += 2) {
                int ny = temp[i].first + dy[j];
                int nx = temp[i].second + dx[j];
                if (isrange(ny, nx) && board[ny][nx])cnt++;
            }
            board[temp[i].first][temp[i].second] += cnt;
        }
        //구름이 어디에있는지
        setcloud(temp);
        
        //5번구름생성
        makecloud(cv);
        //3번은 temp.clear()를 통해서 해야하지만 temp가 스스로 셋팅되기때문에 없어도됨
    }
    int res = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            res += board[i][j];
        }
    }
    cout << res << "\n";
 
}
 
int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    //freopen("input.txt", "r", stdin);
    input();
    solve();
 
}
 
 
cs

 

궁금한점 혹은 모르는점 어떤질문이든 댓글은 언제나 환영입니다.

 

 

'백준' 카테고리의 다른 글

백준 13505 두 수 XOR  (0) 2021.08.22
백준 14906 스러피  (0) 2021.08.19
백준 13900 순서쌍의 곱의 합  (0) 2021.08.16
백준 1024 수열의합  (0) 2021.08.15
백준 1043 거짓말  (0) 2021.08.15