[백준] 20057 마법사 상어와 토네이도

문제 링크

20057번: 마법사 상어와 토네이도

알고리즘

시뮬레이션

풀이

이번 삼성 복기 문제이다. 이 문제는 토네이도를 움직이는 부분과 모래를 배분하는 부분으로 나눌 수 있다. 토네이도가 움직이는 부분을 살펴보면, (좌,하,우,상)을 반복하고 1,1,2,2,…,n-1,n-1,n-1칸 움직이는 것을 알 수 있다. 모래를 배분하는 부분은 토네이도 이동 방향을 기준으로 양방향의 좌표를 직접 구해주었다. 전체적으로 코드가 깔끔하지 못하다. 시간 복잡도는 O(N2)O(N^2).

코드

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

struct Pos {
    int r, c;
};

// 좌하우상
const int dr[] = {0, 1, 0, -1};
const int dc[] = {-1, 0, 1, 0};
const int MAX = 500;
int map[MAX][MAX];
int n;
int answer;

Pos coord(Pos& p, int d) { return {p.r + dr[d], p.c + dc[d]}; }

bool inRange(Pos& p) { return (0 <= p.r && p.r < n) && (0 <= p.c && p.c < n); }

void flutter(Pos p, int d) {
    int sum = 0;
    vector<pair<Pos, double>> pos;
    Pos a = coord(p, (d + 3) % 4);
    Pos aa = coord(a, (d + 3) % 4);
    Pos aaa = coord(a, (d + 2) % 4);
    Pos b = coord(p, (d + 1) % 4);
    Pos bb = coord(b, (d + 1) % 4);
    Pos bbb = coord(b, (d + 2) % 4);
    pos.push_back({a, 0.07});
    pos.push_back({b, 0.07});
    pos.push_back({aa, 0.02});
    pos.push_back({bb, 0.02});
    pos.push_back({aaa, 0.01});
    pos.push_back({bbb, 0.01});
    pos.push_back({coord(a, d), 0.10});
    pos.push_back({coord(b, d), 0.10});
    Pos alpha = coord(p, d);
    pos.push_back({coord(alpha, d), 0.05});
    for (auto& a : pos) {
        int amount = int(map[p.r][p.c] * a.second);
        sum += amount;
        if (inRange(a.first))
            map[a.first.r][a.first.c] += amount;
        else
            answer += amount;
    }
    int remain = map[p.r][p.c] - sum;
    if (inRange(alpha))
        map[alpha.r][alpha.c] += remain;
    else
        answer += remain;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n;
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j) cin >> map[i][j];
    answer = 0;
    Pos x = {n / 2, n / 2};
    int d = 0;
    bool flag = false;
    for (int i = 1; i <= n && !flag; ++i) {
        for (int k = 0; k < 2 && !flag; ++k) {
            for (int j = 0; j < i && !flag; ++j) {
                Pos y = coord(x, d);
                flutter(y, d);
                x = y;
                if (x.r == 0 && x.c == 0) flag = true;
            }
            d = (d + 1) % 4;
        }
    }
    cout << answer << endl;
    return 0;
}

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

GitHub