[백준] 20058 마법사 상어와 파이어스톰

문제 링크

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

알고리즘

시뮬레이션, bfs

풀이

이번 삼성 복기 문제이다. 분할정복법으로 dfs를 사용한다면 더 깔끔한 코드가 나올 것이다. 얼음을 녹일 때 조건에 맞다고 바로 녹이지 않고 한 번에 녹여야 한다는 점을 유의해야 한다. 시간 복잡도는 O(Q22N)O(Q*2^{2N})이다.

코드

#include <algorithm>
#include <cmath>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;

const int dr[] = {0, 1, 0, -1};
const int dc[] = {1, 0, -1, 0};
const int MAX = 64;
int map[MAX][MAX];
int mapSize;
int sum, maxCnt;
int n, q;

bool inRange(int row, int col) {
    return (0 <= row && row < mapSize) && (0 <= col && col < mapSize);
}

void rotate(int row, int col, int l) {
    vector<vector<int>> temp(l, vector<int>(l));
    for (int i = 0; i < l; ++i)
        for (int j = 0; j < l; ++j) temp[i][j] = map[row + l - 1 - j][col + i];
    for (int i = 0; i < l; ++i)
        for (int j = 0; j < l; ++j) map[row + i][col + j] = temp[i][j];
}

void melt() {
    vector<pair<int, int>> cand;
    for (int i = 0; i < mapSize; ++i) {
        for (int j = 0; j < mapSize; ++j) {
            if (map[i][j] == 0) continue;
            int cnt = 0;
            for (int k = 0; k < 4; ++k) {
                int nr = i + dr[k];
                int nc = j + dc[k];
                if (!inRange(nr, nc)) continue;
                if (map[nr][nc]) cnt++;
            }
            if (cnt < 3) cand.push_back({i, j});
        }
    }
    for (auto& c : cand) map[c.first][c.second]--;
}

void bfs() {
    for (int i = 0; i < mapSize; ++i) {
        for (int j = 0; j < mapSize; ++j) {
            if (map[i][j] != 0) {
                queue<pair<int, int>> q;
                q.push({i, j});
                sum += map[i][j];
                map[i][j] = 0;
                int cnt = 1;
                while (!q.empty()) {
                    int r = q.front().first;
                    int c = q.front().second;
                    q.pop();
                    for (int k = 0; k < 4; ++k) {
                        int nr = r + dr[k];
                        int nc = c + dc[k];
                        if (!inRange(nr, nc)) continue;
                        if (map[nr][nc]) {
                            sum += map[nr][nc];
                            map[nr][nc] = 0;
                            q.push({nr, nc});
                            cnt++;
                        }
                    }
                }
                maxCnt = max(maxCnt, cnt);
            }
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n >> q;
    mapSize = (int)pow(2, n);
    for (int i = 0; i < mapSize; ++i)
        for (int j = 0; j < mapSize; ++j) cin >> map[i][j];
    for (int i = 0; i < q; ++i) {
        int l;
        cin >> l;
        int t = (int)pow(2, l);
        for (int i = 0; i < mapSize; i += t)
            for (int j = 0; j < mapSize; j += t)
                rotate(i, j, t);
        melt();
    }
    sum = maxCnt = 0;
    bfs();
    cout << sum << endl << maxCnt << endl;
    return 0;
}

Written by@WOOJIN
自强不息,厚德载物

GitHub