[백준/BOJ] 백준 20056번 : 마법사 상어와 파이어볼

2021. 2. 9. 01:19알고리즘 문제풀이

www.acmicpc.net/problem/20056

 

20056번: 마법사 상어와 파이어볼

첫째 줄에 N, M, K가 주어진다. 둘째 줄부터 M개의 줄에 파이어볼의 정보가 한 줄에 하나씩 주어진다. 파이어볼의 정보는 다섯 정수 ri, ci, mi, si, di로 이루어져 있다. 서로 다른 두 파이어볼의 위치

www.acmicpc.net

구조체로 파이어볼의 정보를 나타냈고, ball_list를 통해 파이어볼의 정보를 저장하여 문제를 풀었다. 

 

코드

#include <iostream>
#include <algorithm>
#include <vector>
#include <utility>
#include <queue>
#include <deque>
#include <map>
#include <cmath>
using namespace std;

int n, m, k;

struct ball {
	int r; //행
	int c; //열
	int m; //질량
	int s; //속력
	int d; //방향
};

vector<ball> ball_list;

int dxdy[8][2] = { {-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1} };

void Move()
{
	vector<ball> ball_board[51][51];

	//파이어볼 이동
	for (int i = 0; i < ball_list.size(); i++)
	{
		ball this_ball = ball_list[i];
		pair<int, int> here = make_pair(this_ball.r, this_ball.c);

		for (int i = 0; i < this_ball.s; i++)
		{
			pair<int, int> there = make_pair(here.first + dxdy[this_ball.d][0], here.second + dxdy[this_ball.d][1]);

			if (there.first > n)
				there.first = 1;
			if (there.second > n)
				there.second = 1;
			if (there.first < 1)
				there.first = n;
			if (there.second < 1)
				there.second = n;

			here = there;
		}
		this_ball.r = here.first;
		this_ball.c = here.second;
		ball_board[here.first][here.second].push_back(this_ball);
	}

	//기존의 파이어볼 정보 지우기
	ball_list.clear();

	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
		{
			int new_r = i;
			int new_c = j;
			int new_m = 0;
			int new_s = 0;
			int new_d1, new_d2, new_d3, new_d4;

			if (ball_board[i][j].size() >= 2) //2개 이상의 파이어볼이 있을때
			{
				for (int k = 0; k < ball_board[i][j].size(); k++)
				{
					new_m += ball_board[i][j][k].m;
					new_s += ball_board[i][j][k].s;
				}

				new_m /= 5; //나누어지는 새로운 파이어볼의 질량
				new_s /= ball_board[i][j].size(); //나누어지는 새로운 파이어볼의 속력


				if (new_m != 0)
				{
					bool odd_d = true;
					bool even_d = true;

					for (int k = 0; k < ball_board[i][j].size(); k++)
					{
						if (ball_board[i][j][k].d % 2 == 0)
							odd_d = false;
						else
							even_d = false;
					}

					//모두 홀수이거나 모두 짝수일때
					if (odd_d || even_d)
					{
						new_d1 = 0;
						new_d2 = 2;
						new_d3 = 4;
						new_d4 = 6;
					}

					else
					{
						new_d1 = 1;
						new_d2 = 3;
						new_d3 = 5;
						new_d4 = 7;
					}

					//나누어진 새로운 파이어볼 정보 저장
					ball_list.push_back({ new_r, new_c, new_m, new_s, new_d1 });
					ball_list.push_back({ new_r, new_c, new_m, new_s, new_d2 });
					ball_list.push_back({ new_r, new_c, new_m, new_s, new_d3 });
					ball_list.push_back({ new_r, new_c, new_m, new_s, new_d4 });
				}
			}

			else if (ball_board[i][j].size() == 1)
			{
				//파이어볼 정보 저장
				ball_list.push_back(ball_board[i][j][0]);
			}
		}
}

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

	cin >> n >> m >> k;

	for (int i = 0; i < m; i++)
	{
		int r, c, m, s, d;

		cin >> r >> c >> m >> s >> d;

		ball_list.push_back({ r,c,m,s,d });
	}

	for (int i = 0; i < k; i++)
	{
		Move(); //k번 이동
	}

	int result = 0;

	for (int i = 0; i < ball_list.size(); i++)
		result += ball_list[i].m;

	cout << result;

	return 0;
}