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

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

by paysmile 2021. 9. 18.

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

 

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

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

www.acmicpc.net

 

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
const int MAX = 50;
struct MOVE { int x, y; };
MOVE mv[4] = { { -1,0 },{ 1,0 },{ 0,-1 },{ 0,1 } }; //위, 아래, 왼, 오(1,2,3,4)
													//shark , move, (expire, move), change(개수, 번호)-> 다 못들어가면 사라짐
int first = 0;
int second = 0;
int third = 0;
int map[MAX][MAX];
pair<int, int> shark;
int n;

void EatFish(int d, int s) {
	int movei = shark.first;
	int movej = shark.second;
	for (int i = 0; i < s; i++) {
		movei += mv[d - 1].x;
		movej += mv[d - 1].y;
		if (movei > 0 && movei <= n && movej > 0 && movej <= n) {
			map[movei][movej] = 0;
		}
	}
}
int ChangeDir(int dir) {
	if (dir == 2) dir = 1;
	else if (dir == 1) dir = 3;
	else if (dir == 3) dir = 0;
	else if (dir == 0) dir = 2;
	return dir;
}
vector<int> SortFish() {
	//왼, 아래, 오, 위 (2, 1, 3, 0)
	vector<int> tmp;
	int dir = 2;
	int movei = shark.first;
	int movej = shark.second;
	int count = 1;
	while (count < n) {
		for (int j = 0; j < 2; j++) {
			for (int i = 0; i < count; i++) {
				movei += mv[dir].x;
				movej += mv[dir].y;
				if (map[movei][movej] != 0) {
					tmp.push_back(map[movei][movej]);
				}
			}
			dir = ChangeDir(dir);
		}
		count++;
	}
	for (int i = 1; i < count; i++) {
		movei += mv[dir].x;
		movej += mv[dir].y;
		if (map[movei][movej] != 0) {
			tmp.push_back(map[movei][movej]);
		}
	}
	return tmp;
}
void PutFish(vector<int> tmp) {
	//put
	memset(map, 0, sizeof(map));
	int dir = 2;
	int movei = shark.first;
	int movej = shark.second;
	int count = 1;
	int index = 0;
	while (count < n) {
		for (int j = 0; j < 2; j++) {
			for (int i = 0; i < count; i++) {
				movei += mv[dir].x;
				movej += mv[dir].y;
				if (index < tmp.size()) {
					map[movei][movej] = tmp[index];
					index += 1;
				}
				else {
					break;
				}
			}
			dir = ChangeDir(dir);
		}
		count++;
	}
	for (int i = 1; i < count; i++) {
		movei += mv[dir].x;
		movej += mv[dir].y;
		if (index < tmp.size()) {
			map[movei][movej] = tmp[index];
			index += 1;
		}
		else {
			break;
		}
	}
}
void MoveFish() {
	//왼, 아래, 오, 위 (2, 1, 3, 0)
	vector<int> tmp = SortFish();
	PutFish(tmp);
}
bool Expire() {
	bool flag = false;
	vector<int> tmp = SortFish();
	vector<int> putfs;
	int count;
	memset(map, 0, sizeof(map));
	for (int i = 0; i < tmp.size(); i++) {
		count = 1;
		int index = i;
		while (index + 1 < tmp.size() && tmp[index] == tmp[index + 1]) {
			index++;
			count++;
		}
		if (count >= 4) {
			if (tmp[i] == 1) first += count;
			else if (tmp[i] == 2) second += count;
			else if (tmp[i] == 3) third += count;
			flag = true;
		}
		else {
			if (i != index) {
				for (int k = i; k <= index; k++) {
					putfs.push_back(tmp[k]);
				}
			}
			else {
				putfs.push_back(tmp[i]);
			}
		}
		if (i != index)
			i = index;
	}
	PutFish(putfs);
	return flag;
}
void ChangeFish() {
	vector<int> tmp = SortFish();
	vector<int> putfs;
	int count, num;
	for (int i = 0; i < tmp.size(); i++) {
		count = 1;
		num = tmp[i];
		int index = i;
		while (index + 1 < tmp.size() && tmp[index] == tmp[index + 1]) {
			index++;
			count++;
			i = index;
		}
		putfs.push_back(count);
		putfs.push_back(num);
	}
	PutFish(putfs);
}
int main(void) {
	int m, d, s;
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cin >> map[i][j];
		}
	}
	shark = make_pair((n+1) / 2, (n+1) / 2);
	for (int i = 0; i < m; i++) {
		cin >> d >> s;
		EatFish(d, s);
		MoveFish();
		while (Expire()) {
			MoveFish();
		}
		ChangeFish();
	}
	int answer = first + 2 * second + 3 * third;
	cout << answer << endl;
}

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

마법사 상어와 토네이도 C++  (0) 2021.09.30
상어 초등학교 C++  (0) 2021.09.18
백준 모노미노도미노 2 C++  (0) 2021.07.26
백준 주사위 윷놀이 C++  (0) 2021.07.21
마법사 상어와 비바라기  (0) 2021.06.28