본문 바로가기
백준 알고리즘/구현

마법사 상어와 블리자드 C++

by paysmile 2022. 2. 3.

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

 

21611번: 마법사 상어와 블리자드

마법사 상어는 파이어볼, 토네이도, 파이어스톰, 물복사버그, 비바라기 마법을 할 수 있다. 오늘 새로 배운 마법은 블리자드이고, 크기가 N×N인 격자에서 연습하려고 한다. N은 항상 홀수이고, (

www.acmicpc.net

 

#include <iostream>
#include <vector>

using namespace std;
const int MAX = 55;
int n, m;
int map[MAX][MAX];
int answer = 0;
vector<pair<int, int>> cmd;
struct MOVE { int x, y; };
MOVE mv[4] = { {-1,0}, {1,0}, {0,-1}, {0,1} };
vector<int> num;

void printmap() {
	cout << endl;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cout << map[i][j] << " ";
		}
		cout << endl;
	}
	cout << endl;
}

void DeleteBall(int d, int s) {
	int movei = (n + 1) / 2;
	int movej = (n + 1) / 2;

	for(int k=0; k<s; k++){
		movei += mv[d].x;
		movej += mv[d].y;

		if (!(movei >= 1 && movei <= n && movej >= 1 && movej <= n)) break;
		map[movei][movej] = 0;
	}
}

void PutBall() {
	num.clear();

	//dir : 2,1,3,0

	int dir = 2;
	int movei = (n + 1) / 2;
	int movej = (n + 1) / 2;

	for (int i = 1; i < n; i++) {
		for (int j = 0; j < 2; j++) {
			for (int count = i; count > 0; count--) {
				movei += mv[dir].x;
				movej += mv[dir].y;

				if (map[movei][movej] != 0) num.push_back(map[movei][movej]);
			}

			if (dir == 2) dir = 1;
			else if (dir == 1) dir = 3;
			else if (dir == 3) dir = 0;
			else if (dir == 0) dir = 2;
		}
	}

	dir = 2;
	for (int i = 1; i < n; i++) {
		movei += mv[dir].x;
		movej += mv[dir].y;

		if (map[movei][movej] != 0) num.push_back(map[movei][movej]);
	}
}

void PushBall() {
	int dir = 2;
	int movei = (n + 1) / 2;
	int movej = (n + 1) / 2;
	int index = 0;

	for (int i = 1; i < n; i++) {
		for (int j = 0; j < 2; j++) {
			for (int count = i; count > 0; count--) {
				movei += mv[dir].x;
				movej += mv[dir].y;

				if (index >= num.size()) {
					map[movei][movej] = 0;
				}
				else {
					map[movei][movej] = num[index];
					index++;
				}
			}

			if (dir == 2) dir = 1;
			else if (dir == 1) dir = 3;
			else if (dir == 3) dir = 0;
			else if (dir == 0) dir = 2;
		}
	}

	dir = 2;
	for (int i = 1; i < n; i++) {
		movei += mv[dir].x;
		movej += mv[dir].y;

		if (index >= num.size()) {
			map[movei][movej] = 0;
		}
		else {
			map[movei][movej] = num[index];
			index++;
		}
	}
}

void MoveBall() {
	PutBall();
	PushBall();
}

bool ExpireBall() {
	bool flag = false;

	PutBall();
	vector<int> tmp;

	for (int i = 0; i < num.size(); i++) {
		int value = num[i];
		int cur = i;
		int count = 1;
		cur++;
		while (cur < num.size() && value == num[cur]) {
			count++;
			cur++;
		}

		if (count >= 4) {
			if (value == 1) {
				answer += count;
			}
			else if (value == 2) {
				answer += (count * 2);
			}
			else if (value == 3) {
				answer += (count * 3);
			}

			i = cur-1;
			flag = true;
		}
		else
			tmp.push_back(value);
	}

	num = tmp;
	if(flag == true) PushBall();

	return flag;
}

void ChangeBall() {
	PutBall();
	
	vector<int> tmp;

	for (int i = 0; i < num.size(); i++) {
		int value = num[i];
		bool flag = false;
		int cur = i;
		int count = 1;
		cur++;
		while (cur < num.size() && value == num[cur]) {
			count++;
			cur++;
			flag = true;
		}

		if (flag == true) {
			tmp.push_back(count);
			tmp.push_back(value);
			i = cur-1;
		}
		else {
			tmp.push_back(1);
			tmp.push_back(value);
		}
	}

	num = tmp;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			map[i][j] = 0;
		}
	}
	PushBall();
}

int main(void) {
	cin >> n >> m;

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cin >> map[i][j];
		}
	}

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

	for (int i = 0; i < cmd.size(); i++) {
		DeleteBall(cmd[i].first,cmd[i].second);
		MoveBall();
		while (ExpireBall()) {
		}
		ChangeBall();
	}

	cout << answer << endl;
}

'백준 알고리즘 > 구현' 카테고리의 다른 글

마법사 상어와 토네이도 C++  (0) 2022.02.15
마법사 상어와 비바라기 C++  (0) 2022.02.05
어항 정리 C++  (0) 2022.01.22
마법사 상어와 복제  (0) 2021.12.03
스타트와 링크 C++  (0) 2021.10.22