[BOJ] 20056번 마법사 상어와 파이어볼(C++)

Alice·2023년 8월 7일
0

풀이 소요시간 : 약 50분


한 세달만에 프로그래머스 에서 백준 으로 넘어와 문제를 풀어보았다. 그 이유는 삼성기출 문제를 풀어보기 위함인데, 3달동안 실력이 꽤나 올라감을 체감했다. 동일한 유형이면서 골드5 난이도인 마법사 상어와 비바라기 문제보다 한단계 어려운 이 문제를 꽤나 수월하게 풀어냈기 때문이다.

30분만에 구현을 끝냈지만, 20분동안 구조체 문법 오류때문에 삽질을 하며 시간을 소요했다. 단순 구현 + 시뮬레이션 문제이기에 별다른 접근 방법은 없다.


전체 코드


#include<iostream>
#include<vector>
#include<map>
using namespace std;
#define MAX 987654321

int N, M, K;
int dx[8] = {-1, -1, 0, 1, 1, 1, 0, -1}; //세로 축
int dy[8] = { 0, 1, 1, 1, 0, -1, -1, -1 }; //가로 축

struct FireBall {
	int x;
	int y;
	int m; //질량
	int s; //방향
	int d; //속도
};

vector<FireBall> Vector;
map<pair<int, int>, vector<FireBall>> Map;


void Input() {
	cin >> N >> M >> K;
	for (int i = 1; i <= M; i++)
	{
		int x, y, m, s, d;
		cin >> x >> y >> m >> s >> d;
		Vector.push_back({ x, y, m, s, d });
	}
}

//좌표 변환기
pair<int, int> Make_Range(int x, int y) {
	if (x == 0) x = N;
	else if (x == N + 1) x = 1;

	if (y == 0) y = N;
	else if (y == N + 1) y = 1;

	return { x, y };
}


int main()
{

	Input();

	//이동을 K 회 명령한다.
	while (K--)
	{
		//Map 초기화
		Map.clear();

		//1. 모든 파이어볼의 이동
		for (auto &E : Vector)
		{
			//고유 방향으로 속력만큼 이동 완료
			for (int i = 0; i < E.s; i++)
			{
				pair<int, int> next = Make_Range(E.x + dx[E.d], E.y + dy[E.d]);
				E.x = next.first;
				E.y = next.second;
			}
			
			//이동된 파이어볼 정보 삽입
			Map[{E.x, E.y}].push_back(E);
		}

		Vector.clear();
		//기존 파이어볼 좌표는 초기화



		//2. 같은 칸의 파이어볼 갯수가 2 이상이면 합치고 나눈다.
		for (auto &E : Map)
		{
			if (E.second.size() == 1)
			{
				Vector.push_back(E.second.front());
				continue;
			}
			else
			{
				vector<FireBall> V = E.second;

				int Size = V.size();
				int Weight = 0;
				int Speed = 0;

				int Odd = 0;
				int Even = 0;
				//무조건 4개로 나뉘게된다.

				
				for (int i = 0; i < V.size(); i++)
				{
					Weight += V[i].m;
					Speed += V[i].s;

					if (V[i].d % 2 == 0) Even++;
					else if (V[i].d % 2 == 1) Odd++;
				}
				

				//새로운 무게, 속력, 방향
				Weight /= 5;
				Speed /= Size;

				if (Weight == 0) continue; //질량이 0인 경우 생성(X) 소멸된다.

				if (Odd == Size || Even == Size)
				{
					for (int i = 0; i <= 6; i += 2)
					{
						Vector.push_back({ E.first.first, E.first.second, Weight, Speed, i });
					}
				}
				else
				{
					for (int i = 0; i <= 6; i += 2)
					{
						Vector.push_back({ E.first.first, E.first.second, Weight, Speed, i + 1 });
					}
				}
				//새로운 파이어볼 좌표 삽입 완료

			}

		}

	}


	//남아있는 파이어볼의 질량의 합
	int Ans = 0;
	for (auto &E : Vector)
	{
		Ans += E.m;
	}
	cout << Ans << '\n';

}
profile
SSAFY 11th

0개의 댓글