October 21, 2020
시뮬레이션
이번 삼성 복기 문제이다. 이 문제는 토네이도를 움직이는 부분과 모래를 배분하는 부분으로 나눌 수 있다. 토네이도가 움직이는 부분을 살펴보면, (좌,하,우,상)을 반복하고 1,1,2,2,…,n-1,n-1,n-1칸 움직이는 것을 알 수 있다. 모래를 배분하는 부분은 토네이도 이동 방향을 기준으로 양방향의 좌표를 직접 구해주었다. 전체적으로 코드가 깔끔하지 못하다. 시간 복잡도는 .
#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;
}