백준 - 마법사 상어와 블리자드 (21611번)과 유사한 문제이다.
2차원 배열을 [(n-1)/2, (n-1)/2] 부터 시작해서 달팽이 도는 순서로 [0, 0]까지 움직이면 된다.
움직일 때마다 토네이도를 발생시켜야 하는데, 이는 각 방향과 좌표마다 1%, 2%, 5%, 7%, 10%로 미리 지정된 좌표가 있기 때문에 상수 배열로 정의해서 사용하면 된다.
그 후 좌표가 OutofBounds가 될 때마다 맵 밖으로 나가는 것이기 때문에 정답에 더해주면 된다.
코드는 아래와 같다.
#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
typedef struct __pos {
int row;
int col;
}pos;
int n;
int map[500][500];
int rowDir[4] = { 0, 1, 0, -1 };
int colDir[4] = { -1, 0, 1, 0 };
int answer = 0;
pos collection[10];
int collectionRow[4][10] = {
{ -2, 2, -1, 1, -1, 1, -1, 1, 0, 0 },
{ 0, 0, 0, 0, -1, -1, 1, 1, 2, 1 },
{ -2, 2, -1, 1, -1, 1, -1, 1, 0, 0 },
{ 0, 0, 0, 0, 1, 1, -1, -1, -2, -1 }
};
int collectionCol[4][10] = {
{ 0, 0, 0, 0, 1, 1, -1, -1, -2, -1 },
{ -2, 2, -1, 1, -1, 1, -1, 1, 0, 0 },
{ 0, 0, 0, 0, -1, -1, 1, 1, 2, 1 },
{ -2, 2, -1, 1, -1, 1, -1, 1, 0, 0 }
};
float amount[9] = { 0.02, 0.02, 0.07, 0.07, 0.01, 0.01, 0.1, 0.1, 0.05 };
const inline bool is_safe(int row, int col)
{
if (row < 0 || row > n - 1 || col < 0 || col > n - 1)
return false;
return true;
}
const inline void get_pos(int row, int col, int dir)
{
for (int i = 0; i < 10; i++) {
collection[i].row = row + collectionRow[dir][i];
collection[i].col = col + collectionCol[dir][i];
}
}
void tornado(int row, int col, int dir)
{
// 좌, 남, 우, 상
get_pos(row, col, dir);
int move_amount[10];
int total = 0;
for (int i = 0; i < 9; i++) {
move_amount[i] = (int)map[row][col] * amount[i];
total += move_amount[i];
}
move_amount[9] = map[row][col] - total;
for (int i = 0; i < 10; i++) {
if (is_safe(collection[i].row, collection[i].col))
map[collection[i].row][collection[i].col] += move_amount[i];
else
answer += move_amount[i];
}
map[row][col] = 0;
}
void solve()
{
int row = (n - 1) / 2;
int col = (n - 1) / 2;
int nrow = row, ncol = col;
int iter = -1, dir = -1, len = 0;
while (1) {
if (nrow == 0 && ncol == 0)
break;
iter++;
dir = (dir + 1 ) % 4;
if (iter % 2 == 0)
len++;
for (int i = 0; i < len; i++) {
if (nrow == 0 && ncol == 0)
break;
nrow = nrow + rowDir[dir];
ncol = ncol + colDir[dir];
tornado(nrow, ncol, dir);
}
}
}
int main(void)
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cin >> n;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
cin >> map[i][j];
solve();
cout << answer << "\n";
return 0;
}