저는 구름의 좌표들을 queue
에 담고
queue
를 순회하면서 이동하거나, 물을 뿌리는 로직으로 구성했습니다.
그냥 시키는대로 하면 되는 구현 문제였습니다.
#define RAINBOW 0
#define BLACK -1
#include <bits/stdc++.h>
using namespace std;
int n, m;
int board[50][50], mark[50][50];
int my[8] = { 0, -1, -1, -1, 0, 1, 1, 1 };
int mx[8] = { -1, -1, 0, 1, 1, 1, 0, -1 };
int diagonal[4] = { 1, 3, 5, 7 };
queue<tuple<int, int, int>> q;
int adjust(int c) {
return c < 0 ? c + n : c >= n ? c - n : c;
}
int main(void) {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> m;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
cin >> board[i][j];
// 구름 초기 좌표 push
q.push({ n - 1, 0, 0 });
q.push({ n - 1, 1, 0 });
q.push({ n - 2, 0, 0 });
q.push({ n - 2, 1, 0 });
while (m--) {
int d, s;
cin >> d >> s;
d--;
s %= n;
int size = q.size();
// 구름 이동한 후에 해당 좌표 1 증가
while (size--) {
int y, x, w;
tie(y, x, w) = q.front();
q.pop();
int ny = adjust(y + my[d] * s);
int nx = adjust(x + mx[d] * s);
board[ny][nx]++;
q.push({ ny, nx, 0 });
}
size = q.size();
// 구름 좌표 순회하면서, 대각선 방향의 물의 양에 따라 증가할 물 저장
while (size--) {
int y, x, w;
tie(y, x, w) = q.front();
q.pop();
for (int d : diagonal) {
int dy = y + my[d];
int dx = x + mx[d];
if (dy < 0 || dy >= n || dx < 0 || dx >= n) continue;
if (board[dy][dx] >= 1) w++;
}
q.push({ y, x, w });
}
// 구름 사라지면서 해당 자리에 물 뿌리기
while (!q.empty()) {
int y, x, w;
tie(y, x, w) = q.front();
q.pop();
board[y][x] += w;
mark[y][x] = 1; // 해당 자리는 구름이 생기면 안됨
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
// 마크가 안돼있고, 물양이 2이상일 때
if (!mark[i][j] && board[i][j] >= 2) {
q.push({ i, j, 0 });
board[i][j] -= 2;
}
mark[i][j] = 0;
}
}
}
int ans = 0;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
ans += board[i][j];
cout << ans;
return 0;
}