본문 바로가기
Algorithm/BOJ

boj 21610 - 마법사 상어와 비바라기(구현, 좌표문제)

by Ellery 2021. 7. 17.

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

 

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

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

www.acmicpc.net

- 구현 중에 구름의 좌표 이동 때문에 골치아파서 오래걸림. 

특정 좌표의 행,열 (r,c)를 알고 있을 때 이동한 좌표를 (nr, nc)라고 정의한다. 

좌표 범위가 0~n-1이라 정의했을 때

nr = ((r + 방향 * 이동거리)  % n + n) % n 으로 정의하였다.
- 좌표가 정방향으로 N-1을 넘어갔을 때 %n을 나눠주고, 역방향으로 0을 넘어갔을 때 %n으로 나눠준 뒤 +n을 해서 양수로 만든 다음 다시 %n 연산을 한다. 

#include <cstring>
#include <iostream>
#include <vector>
#define pii pair<int, int>
using namespace std;

const int dr[] = {0, 0, -1, -1, -1, 0, 1, 1, 1};  // 0, ←, ↖, ↑, ↗, →, ↘, ↓, ↙
const int dc[] = {0, -1, -1, 0, 1, 1, 1, 0, -1};  // 0  1  2  3  4  5  6  7  8

int board[50][50];
bool erased[50][50];
int n, m, total;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    cin >> n >> m;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            cin >> board[i][j];
        }
    }

    vector<pii> cloud = {{n - 1, 0}, {n - 1, 1}, {n - 2, 0}, {n - 2, 1}};
    vector<pii> erasedList;
    while (m--) {
        erasedList.clear();
        memset(erased, false, sizeof(erased));

        int d, s;  // 방향, 거리
        cin >> d >> s;

        // 1. 구름 이동 2. 물 1 증가
        for (pii& axis : cloud) {
            int r = axis.first;
            int c = axis.second;
            int nr = ((r + dr[d] * s) % n + n) % n;
            int nc = ((c + dc[d] * s) % n + n) % n;

            ++board[nr][nc];
            erased[nr][nc] = true;
            erasedList.push_back({nr, nc});
        }

        // 3. 구름 사라짐
        cloud.clear();

        // 4. 물복사 마법
        for (pii& axis : erasedList) {
            int water = 0;
            int r = axis.first;
            int c = axis.second;

            for (int d = 2; d <= 8; d += 2) {
                int nr = r + dr[d];
                int nc = c + dc[d];
                if (0 > nr || 0 > nc || nr >= n || nc >= n) continue;
                if (board[nr][nc] == 0) continue;

                ++water;
            }
            board[r][c] += water;
        }

        // 5. 물 2 이상이면 구름 생기고 -2
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                if (board[i][j] >= 2 && !erased[i][j]) {
                    cloud.push_back({i, j});
                    board[i][j] -= 2;
                }
            }
        }
    }

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            total += board[i][j];
        }
    }

    cout << total;
    return 0;
}

'Algorithm > BOJ' 카테고리의 다른 글

BOJ 2263 - 트리의 순회(tree)  (0) 2021.07.20
BOJ 1991 - 트리 순회(tree)  (0) 2021.07.19
boj 19237 - 어른 상어(구현)  (0) 2021.07.08
boj 17140 - 이차원배열과 연산(구현, 정렬)  (0) 2021.07.08
[BOJ]10026 - 적록색약(dfs)  (0) 2021.07.03