백준 - 마법사 상어와 토네이도 (20057번)

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

백준 삼성

목록 보기
12/23

백준 - 마법사 상어와 토네이도 (20057번)

백준 - 마법사 상어와 블리자드 (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;
}
profile
내가 보려고 만든 블로그

0개의 댓글

관련 채용 정보