비교적 간단한 구현문제다.
주의할 점은 구름이 움직일 때 행, 열의 값이 0 이하가 되면 n-1이 되고, n 이상이 되면 0이 되는 조건이 있다.
반대로 물복사 버그를 할 때에는 일반적인 OutofBounds 조건이 있으니 주의해주면 된다.
구름을 다시 생성할 땐, 이번 단계에서 사라진 구름들의 위치에는 다시 구름을 생성할 수 없으니 이것도 주의해줘야 한다.
12ms가 나왔는데, 시간을 더 줄이고 싶으면 vector로 관리하는 구름들을 배열로 바꿔주면 될 것 같다.
#include <cstdio>
#include <vector>
#include <iostream>
using namespace std;
int n, m;
int map[51][51];
int move_info[101][2];
int rowDir[8] = { 0, -1, -1, -1, 0, 1, 1, 1 };
int colDir[8] = { -1, -1, 0, 1, 1, 1, 0, -1 };
int copyRowDir[4] = { -1, -1, 1, 1 };
int copyColDir[4] = { -1, 1, -1, 1 };
typedef struct __pos{
int row;
int col;
}pos;
vector<pos> winds;
void Print_Winds(const char* s)
{
printf("%s\n", s);
printf("Winds : ");
for (int i = 0; i < winds.size(); i++)
printf("[%d %d] ", winds[i].row, winds[i].col);
printf("\nEnd of Print_Winds\n");
}
void Print_Map(const char* s)
{
printf("%s\n", s);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
printf("%d \t", map[i][j]);
printf("\n");
}
printf("End of Print_Map\n");
}
void init_winds()
{
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
pos wind;
wind.row = (n - 2) + i;
wind.col = j;
winds.push_back(wind);
}
}
}
const inline bool is_safe(int row, int col)
{
if (row < 0 || col < 0 || row > n - 1 || col > n - 1)
return false;
return true;
}
void wind_move_rainy(int dir, int len)
{
for (int i = 0; i < winds.size(); i++) {
pos &wind = winds[i];
//printf("Wind [%d %d]\n", wind.row, wind.col);
int nrow = wind.row, ncol = wind.col;
// 구름이 dir 방향으로 len만큼 이동
for (int j = 0; j < len; j++) {
nrow = nrow + rowDir[dir];
ncol = ncol + colDir[dir];
// 0의 위에는 n-1이 있고, n-1의 밑에는 0이 있도록 재조정
nrow = nrow < 0 ? n - 1 : nrow;
ncol = ncol < 0 ? n - 1 : ncol;
nrow = nrow > n - 1 ? 0 : nrow;
ncol = ncol > n - 1 ? 0 : ncol;
}
// 옮겨진 구름의 위치를 업데이트
wind.row = nrow;
wind.col = ncol;
// 각 구름에서 비가 내려 구림이 잇는 칸의 바구니에 저장된 물의 양이 1 증가한다.
map[nrow][ncol]++;
}
}
void water_copy()
{
for (int i = 0; i < winds.size(); i++) {
pos wind = winds[i];
for (int dir = 0; dir < 4; dir++) {
int nrow = wind.row + copyRowDir[dir];
int ncol = wind.col + copyColDir[dir];
if (!is_safe(nrow, ncol))
continue;
if (map[nrow][ncol] == 0)
continue;
map[wind.row][wind.col] += 1;
}
}
}
void generate_wind()
{
vector<vector<int>> exist(n, vector<int>(n, 0));
// 구름이 사라진 곳에 새로 생기면 안되므로, 미리 체크해둠
for (int i = 0; i < winds.size(); i++) {
pos wind = winds[i];
exist[wind.row][wind.col] = 1;
}
winds.clear();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (map[i][j] < 2)
continue;
if (exist[i][j] == 1)
continue;
map[i][j] -= 2;
pos wind = { i, j };
winds.push_back(wind);
}
}
}
void solve(int dir, int len)
{
wind_move_rainy(dir, len);
water_copy();
generate_wind();
}
int get_answer()
{
int result = 0;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
result += map[i][j];
return result;
}
int main(void)
{
int result = 0;
cin >> n >> m;
for (int i = 0; i < n; i++)
for(int j=0;j<n;j++)
cin >> map[i][j];
for (int i = 0; i < m; i++)
cin >> move_info[i][0] >> move_info[i][1];
init_winds();
for (int i = 0; i < m; i++)
solve(move_info[i][0] - 1, move_info[i][1]);
result = get_answer();
cout << result << "\n";
return 0;
}