[BOJ][삼성기출] 20057. 마법사 상어와 토네이도

gyeong·2021년 4월 19일
0

PS

목록 보기
35/46

문제 접근

시뮬레이션 문제이다. 주어진 조건에 맞추어 구현하면 됨.

까다로웠던 점

  1. 토네이도 구현
    총 길이가 1씩 늘어나는 토네이도를 구현할 때 복잡하게 생각했다. for문을 두 번 돌리면 되는 거였다.
  2. 좌표 매핑
    토네이도가 방향을 바꿀 때마다 모래가 흩어지는데, 이 좌표를 하나하나 다 구해야 한다.
  3. 흩어지는 모래
    기존에 있던 모래에서 흩어지는 모래의 양을 감소시키는데, 이때 다음으로 흩어질 모래를 구할 때 기존의 모래(즉, 처음 모래의 값)에서 값을 계산해야 한다.
    이를 구현하기 위해 Temp 변수에다 최초의 모래 값을 저장해두고 Temp 값으로 흩어질 모래의 양을 구함.

풀이

#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;

int N, rst, cx, cy, dir;
int map[500][500];

int dx[] = { 0, 0, 1, -1 };
int dy[] = { 1, -1, 0, 0 };

int DX[4][10] = { { -1, 1, -1, 1, -1, 1, -2, 2, 0, 0 },{ -1, 1, -1, 1, -1, 1, -2, 2, 0, 0 },
				  { 0, 0, 1, 1, 2, 2, 1, 1, 3, 2}, { 0, 0, -1, -1, -2, -2, -1, -1, -3, -2} };
int DY[4][10] = { { 0, 0, 1, 1, 2, 2, 1, 1, 3, 2}, { 0, 0, -1, -1, -2, -2, -1, -1, -3, -2},
				  { -1, 1, -1, 1, -1, 1, -2, 2, 0, 0}, {-1, 1, -1, 1, -1, 1, -2, 2, 0, 0} };
int percent[9] = { 1, 1, 7, 7, 10, 10, 2, 2, 5 };

void input() {
	cin >> N;
	memset(map, 0, sizeof(map));
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= N; j++) {
			cin >> map[i][j];
		}
	}
}

int is_range(int x, int y) {
	if (x >= 1 && x <= N && y >= 1 && y <= N) return true;
	return false;
}

int change_dir(int Dir) {
	if (Dir == 0) return 3;
	if (Dir == 1) return 2;
	if (Dir == 2) return 0;
	if (Dir == 3) return 1;
}

void spread() {
	int xx = cx + dx[dir];
	int yy = cy + dy[dir];

	if (map[xx][yy] == 0) return;

	int Sand = map[xx][yy];
	int Temp = Sand;
	for (int i = 0; i < 9; i++)
	{
		int nx = cx + DX[dir][i];
		int ny = cy + DY[dir][i];
		int Plus = (Temp * percent[i]) / 100;

		if (!is_range(nx, ny)) rst += Plus;
		else map[nx][ny] += Plus;

		Sand -= Plus;
	}
	int nx = cx + DX[dir][9];
	int ny = cy + DY[dir][9];

	if (!is_range(nx, ny)) rst += Sand;
	else map[nx][ny] += Sand;
	map[xx][yy] = 0;
}

void solve() {
	cx = (N + 1) / 2; cy = (N + 1) / 2; dir = 1; rst = 0;
	int move_count = 1;

	while (true) {
		for (int i = 0; i < 2; i++) {
			for (int j = 0; j < move_count; j++) {
				spread();
				cx += dx[dir];
				cy += dy[dir];
			}
			dir = change_dir(dir);
		}
		move_count++;
		if (move_count == N) {
			for (int j = 0; j < move_count; j++) {
				spread();
				cx += dx[dir];
				cy += dy[dir];
			}
			break;
		}
	}
}

int main() {
	input();
	solve();
	cout << rst << endl;
}
profile
내가 보려고 만든 벨로그

0개의 댓글