[백준/BOJ] 백준 21610번 : 마법사 상어와 비바라기

2021. 6. 28. 00:47알고리즘 문제풀이

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

 

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

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

www.acmicpc.net

구름이 이동하는 함수, 비가 내리는 함수, 물 복사를 하는 함수, 구름이 생기는 함수를 만들어서 문제를 해결했다.

 

코드

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

int n, m;
int board[51][51];
vector<pair<int, int>> move_info; //(방향,거리)
int dxdy[9][2] = { {0,0}, {0,-1},{-1,-1},{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1} };
int croos_dxdy[4][2] = { {-1,-1},{-1,1},{1,1},{1,-1} };
vector<pair<int, int>> cloud;

//구름의 이동
void Move(int d, int s)
{
	for (int i = 0; i < cloud.size(); i++)
	{
		pair<int, int> here = cloud[i];
		pair<int, int> there = here;

		for (int j = 0; j < s; j++)
		{
			there = make_pair(there.first + dxdy[d][0], there.second + dxdy[d][1]);

			if (there.first == n + 1)
				there.first = 1;
			else if (there.first == 0)
				there.first = n;

			if (there.second == n + 1)
				there.second = 1;
			else if (there.second == 0)
				there.second = n;
		}

		cloud[i] = there;
	}
}

//비가 내림
void Rain()
{
	for (int i = 0; i < cloud.size(); i++)
	{
		pair<int, int> here = cloud[i];
		board[here.first][here.second]++;
	}
}

//물 복사
void Water_copy()
{
	for (int i = 0; i < cloud.size(); i++)
	{
		pair<int, int> here = cloud[i];
		int cnt = 0;

		for (int dir = 0; dir < 4; dir++)
		{
			pair<int, int> there = make_pair(here.first + croos_dxdy[dir][0], here.second + croos_dxdy[dir][1]);

			if (there.first >= 1 && there.first <= n && there.second >= 1 && there.second <= n && board[there.first][there.second] >= 1)
				cnt++;
		}

		board[here.first][here.second] += cnt;
	}
}

//구름 생기기
void New_cloud()
{
	vector<vector<int>> before_cloud(51, vector<int>(51, 0)); //이전 구름 위치 체크
	for (int i = 0; i < cloud.size(); i++)
	{
		before_cloud[cloud[i].first][cloud[i].second] = 1;
	}
	cloud.clear();

	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
		{
			//이전 구름의 위치가 아니었고, 물의 양이 2 이상인 칸
			if (before_cloud[i][j] == 0 && board[i][j] >= 2)
			{
				cloud.push_back(make_pair(i, j));
				board[i][j] -= 2;
			}
		}
}

//물의 합
int Sum()
{
	int ret = 0;

	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			ret += board[i][j];

	return ret;
}

int main()
{
	cin.tie(NULL);
	ios_base::sync_with_stdio(false);

	cin >> n >> m;

	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
		{
			int input;
			cin >> input;

			board[i][j] = input;
		}

	for (int i = 0; i < m; i++)
	{
		int d, s;
		cin >> d >> s;

		move_info.push_back(make_pair(d, s));
	}

	//초기 비구름
	cloud.push_back(make_pair(n, 1));
	cloud.push_back(make_pair(n, 2));
	cloud.push_back(make_pair(n - 1, 1));
	cloud.push_back(make_pair(n - 1, 2));

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

		Move(d, s);
		Rain();
		Water_copy();
		New_cloud();
	}

	cout << Sum();

	return 0;
}