와이유스토리

[시뮬레이션] 백준 20056 마법사 상어와 파이어볼 C++ 본문

코딩테스트/시뮬레이션

[시뮬레이션] 백준 20056 마법사 상어와 파이어볼 C++

유(YOO) 2022. 2. 8. 10:47
#include<bits/stdc++.h>

using namespace std;

struct Ball {
	int m, s, d; // 질량, 속력, 방향
	Ball* next; // 같은 위치의 볼들
};

struct State {
	int sumM, sumS, sumD, dir, nCnt, lCnt; // 질량 합, 속력 합, 방향 합, 최종 방향, 현재 볼 개수, 나중 볼 개수
	Ball balls; // 헤드 노드 (포인터 선언은 까다로움)
};

int bufCnt, N, M, K, ans;
int dx[8] = { 0,1,1,1,0,-1,-1,-1 };
int dy[8] = { -1,-1,0,1,1,1,0,-1 };
Ball ball[10000000];
State board[52][52];

void addBall(int r, int c, int m, int s, int d) {
	ball[bufCnt].m = m;
	ball[bufCnt].s = s;
	ball[bufCnt].d = d;
	ball[bufCnt].next = nullptr;

	Ball* temp = (&ball[bufCnt]);
	bufCnt++;

	Ball* ptr = (&board[r][c].balls);
	temp->next = ptr->next;
	ptr->next = temp;
}

void start() {
	for (int t = 0; t < K; t++) {
		for (int i = 1; i <= N; i++) {
			for (int j = 1; j <= N; j++) {
				if (board[i][j].nCnt == 0) continue;
				Ball* ptr = (&board[i][j].balls);

				while (ptr->next) {
					int newX = j + (dx[(ptr->next->d)] * (ptr->next->s));
					int newY = i + (dy[(ptr->next->d)] * (ptr->next->s));

					newX = (newX % N) + 1; newY = (newY % N) + 1; // 배열 인덱스 나머지 연산
					if (newX <= 0) newX = N + newX;
					if (newY <= 0) newY = N + newY;
					if (newX > N) newX = (newX - N);
					if (newY > N) newY = (newY - N);
					
					board[newY][newX].sumM += ptr->next->m;
					board[newY][newX].sumS += ptr->next->s;
					board[newY][newX].sumD += ptr->next->d; // 공 하나일 경우를 위하여 방향 값 저장해야 함
					if ((ptr->next->d) & 1) board[newY][newX].dir += 1; // 방향 결정
					board[newY][newX].lCnt += 1;
					
					ptr->next = ptr->next->next;

				}
				board[i][j].nCnt = 0;
			}
		}

		ans = 0;
		for (int i = 1; i <= N; i++) {
			for (int j = 1; j <= N; j++) {
				if (board[i][j].lCnt > 1) { // 2개 이상
					int m = floor(board[i][j].sumM / 5);
					int s = floor(board[i][j].sumS / board[i][j].lCnt);
					int dir = 1;

					if ((board[i][j].lCnt == board[i][j].dir) || (board[i][j].dir == 0)) dir = 0;
					if (m != 0) { // 질량 0이면 소멸
						for (int k = 0; k < 4; k++) { // 인덱스 조심
							addBall(i, j, m, s, dir);
							board[i][j].nCnt++;
							ans += m;
							dir = dir + 2;
						}
					}
				}
				else if (board[i][j].lCnt == 1) { // 공 하나일 경우 조심
					addBall(i, j, board[i][j].sumM, board[i][j].sumS, board[i][j].sumD);
					board[i][j].nCnt = board[i][j].lCnt;
					ans += board[i][j].sumM;
				}

				board[i][j].lCnt = 0;
				board[i][j].sumM = 0;
				board[i][j].sumS = 0;
				board[i][j].sumD = 0;
				board[i][j].dir = 0;
			}
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);

	cin >> N >> M >> K;
	for (int i = 0; i < M; i++) {
		int r, c, m, s, d;
		cin >> r >> c >> m >> s >> d;
		addBall(r, c, m, s, d);
		board[r][c].nCnt++;
	}

	start();

	cout << ans;
}
Comments