백준 - 마법사 상어와 비바라기 (21610번)

well-life-gm·2021년 11월 3일
0

백준 삼성

목록 보기
7/23

백준 - 마법사 상어와 비바라기 (21610번)

비교적 간단한 구현문제다.
주의할 점은 구름이 움직일 때 행, 열의 값이 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;
}
profile
내가 보려고 만든 블로그

0개의 댓글

관련 채용 정보