알고리즘/삼성 기출

[백준/C++] 21610번 마법사 상어와 비바라기 - 삼성SW기출

수디sudy 2022. 4. 4. 16:33

문제 : https://www.acmicpc.net/problem/21610

 

21610번: 마법사 상어와 비바라기

마법사 상어는 파이어볼, 토네이도, 파이어스톰, 물복사버그 마법을 할 수 있다. 오늘 새로 배운 마법은 비바라기이다. 비바라기를 시전하면 하늘에 비구름을 만들 수 있다. 오늘은 비바라기

www.acmicpc.net

 

 

 

[ 시뮬레이션 ]

이 문제는 BFS나 DFS도 필요없는 찐찐찐 시뮬레이션 문제다. (지금까지 푼 것 중에 가장 쉬움..)

 

 

위의 과정 그대로 짜면 정말 끝이다. 

1) 구름 이동 : 1번째 행-N번째 행, 1번째 열-N번째 열이 연결 되어 있는 부분만 조심 하면 된다.

if (ny < 1)
    ny += N;
if (nx < 1)
    nx += N;
if (ny > N)
    ny -= N;
if (nx > N)
    nx -= N;

나는 이런 식으로 if문을 통해서 간단히 연결 해줬다.

 

또, 이동하는 크기 s 가 N보다 큰 경우 연결이 제대로 되지 않고 어차피 규칙적으로 움직이기 때문에

아래 처럼 s를 N보다 작은 수로 만들어줬다.

while (1)
	{
		if (s <= N)
			break;

		if (s > N)
			s -= N;
	}

 

3) 구름이 사라지는것은 함수는 만들었지만 따로 사용하지 않았다.

 -> 4번과 5번 과정에서 원래 구름이 있던 좌표가 계속해서 필요했기 때문.

 

이 점들만 주의하면 바로 풀 수 있는 간단한 문제다 1시간 20분만에 성공😉💕

 

 

#include <iostream>
#include <vector>
using namespace std;

int N, M;
const int MAX = 51;

int bucket_map[MAX][MAX] = {0, }; //바구니에 저장된 물 양
int cloud_map[MAX][MAX] = { 0, }; //구름 위치
vector<pair<int, int>> cmd; //구름 이동 정보

//구름 이동 방향 : 좌, 좌상, 상, 상우, 우, 우하, 하, 하좌
const int dy[9] = {0,0,-1,-1,-1,0,1,1,1};
const int dx[9] = {0,-1,-1,0,1,1,1,0,-1};

//물복사버그 마법 시전 방향 : 대각선
const int diagonal_dy[4] = {-1,-1,1,1};
const int diagonal_dx[4] = {-1,1,-1,1};


void print(int map[MAX][MAX])
{
	for (int y = 1; y <= N; y++)
	{
		for (int x = 1; x <= N; x++)
		{
			cout << map[y][x] << " ";
		}
		cout << endl;
	}
	cout << endl;
}

void move_cloud(int d, int s)
{
	int temp[MAX][MAX] = { 0, };

	while (1)
	{
		if (s <= N)
			break;

		if (s > N)
			s -= N;
	}
	

	for (int y = 1; y <= N; y++)
	{
		for (int x = 1; x <= N; x++)
		{
			if (cloud_map[y][x])
			{
				int ny = y + s * dy[d];
				int nx = x + s * dx[d];

				if (ny < 1)
					ny += N;
				if (nx < 1)
					nx += N;
				if (ny > N)
					ny -= N;
				if (nx > N)
					nx -= N;

				temp[ny][nx] = 1;
			}
		}
	}

	for (int y = 1; y <= N; y++)
	{
		for (int x = 1; x <= N; x++)
		{
			cloud_map[y][x] = temp[y][x];
		}
	}
}

void rain()
{
	for (int y = 1; y <= N; y++)
	{
		for (int x = 1; x <= N; x++)
		{
			if (cloud_map[y][x])
				bucket_map[y][x]++;
		}
	}
}

void disappear_cloud()
{
	for (int y = 1; y <= N; y++)
	{
		for (int x = 1; x <= N; x++)
		{
			cloud_map[y][x] = 0;
		}
	}
}

void copy_water()
{
	int temp[MAX][MAX] = { 0, };
	for (int y = 1; y <= N; y++)
	{
		for (int x = 1; x <= N; x++)
		{
			if (cloud_map[y][x])
			{
				int cnt = 0;
				for (int dir = 0; dir < 4; dir++)
				{
					int ny = y + diagonal_dy[dir];
					int nx = x + diagonal_dx[dir];
					
					if (ny > N || nx > N || ny < 1 || nx < 1)	continue;

					if (bucket_map[ny][nx])
						cnt++;
				}
				temp[y][x] += cnt;
			}
		}
	}

	for (int y = 1; y <= N; y++)
	{
		for (int x = 1; x <= N; x++)
		{
			bucket_map[y][x] += temp[y][x];
		}
	}
}

void appear_cloud()
{
	int temp[MAX][MAX] = { 0, };

	for (int y = 1; y <= N; y++)
	{
		for (int x = 1; x <= N; x++)
		{
			if (bucket_map[y][x] >= 2 && !cloud_map[y][x])
			{
				temp[y][x] = 1;
				bucket_map[y][x] -= 2;
			}
		}
	}

	for (int y = 1; y <= N; y++)
	{
		for (int x = 1; x <= N; x++)
		{
			cloud_map[y][x] = temp[y][x];
		}
	}
}

int main()
{
	ios_base::sync_with_stdio(false);
	cout.tie(NULL);
	cin.tie(NULL);
	
	cin >> N >> M;

	for (int y = 1; y <= N; y++)
	{
		for (int x = 1; x <= N; x++)
		{
			cin >> bucket_map[y][x];
		}
	}

	for (int i = 0; i < M; i++)
	{
		int d, s;
		cin >> d >> s;
		cmd.push_back(make_pair(d, s));
	}

	cloud_map[N][1] = cloud_map[N][2] = cloud_map[N - 1][1] = cloud_map[N - 1][2] = 1;

	for (int i = 0; i < M; i++)
	{
		int d = cmd[i].first;
		int s = cmd[i].second;

		move_cloud(d, s);

		rain();

		copy_water();

		appear_cloud();

	}

	int cnt = 0;
	for (int y = 1; y <= N; y++)
	{
		for (int x = 1; x <= N; x++)
		{
			cnt += bucket_map[y][x];
		}
	}

	cout << cnt << "\n";
	
	
	return 0;
}