21611 마법사 상어와 블리자드
본문 바로가기
알고리즘 모음집/알고리즘 (Algorithm)

21611 마법사 상어와 블리자드

by KyeongMin 2021. 5. 2.
728x90
반응형

www.acmicpc.net/problem/21611

 

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

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

www.acmicpc.net

 

 

 

#include<stdio.h>
#include<iostream>
#include<vector>
#include<string.h>
using namespace std;
#define NS 49//최대 배열의 크기
int N;//49까지 입력 홀수
int M;//공격하는 횟수
int ret1;//결과값 저장
int ret2;
int ret3;
int board[NS][NS];//구슬이 저장될 배열
int dy[] = { 0,-1,1,0,0 };//인덱스 1부터 상 하 좌 우
int dx[] = { 0,0,0,-1,1 };

int s_dy[] = { 0,1,0,-1 };//달팽이 배열의 방향 순서
int s_dx[] = { -1,0,1,0 };//좌 하 우 상 순서
void init();//초기화 및 입력
void simulation();//시뮬레이션 시작
void fire(int dir, int s);
int main(void) {
	int testCase = 1;
	//scanf("%d", &testCase);
	for (int tc = 1; tc <= testCase; tc++) {
		init();
		simulation();
		int ret = (ret1)+(2 * ret2) + (3 * ret3);
		printf("%d\n", ret);
	}

	return 0;
}

void init() {//초기화 및 초기 입력
	//초기화
	N = M = ret1 = ret2 = ret3 = 0;
	memset(board, 0, sizeof(board));
	scanf("%d %d", &N, &M);
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			scanf("%d", &board[i][j]);
		}
	}
}
void snailRotation() {
	int cy = N / 2; int cx = cy;//센터값
	int dir = 0;
	int n = 1;
	int cnt = 0;//두번 주기로 변경
	vector<int>num;
	while (1) {
		for (int i = 0; i < n; i++) {
			cy += s_dy[dir]; cx += s_dx[dir];//이동
			if (cy == 0 && cx == 0) {
				cx = 999;
				break;
			}
			if (board[cy][cx] != 0) {//숫자 저장
				num.push_back(board[cy][cx]);
				board[cy][cx] = 0;//초기화
			}
		}
		if (cx == 999)break;
		dir++; if (dir == 4)dir = 0;//방향 변경
		cnt++;
		if (cnt == 2) {
			n++;
			cnt = 0;//리셋
		}
	}

}
void fire(int dir,int s) {//파이어볼
	int cy = N / 2,cx = cy;//상어 위치
	for (int i = 0; i < s; i++) {
		cy += dy[dir]; cx += dx[dir];
		if (board[cy][cx] != 0) {
			//if (board[cy][cx] == 1)ret1++;
			//if (board[cy][cx] == 2)ret2++;
			//if (board[cy][cx] == 3)ret3++;
			board[cy][cx] = 0;
		}
	}

	//전체 한번 다시 정렬하기 위해 숫자 수집
	cy = N / 2; cx = cy;//센터값
    dir = 0;
	int n = 1;
	int cnt = 0;//두번 주기로 변경
	vector<int>num;
	while (1) {
		for (int i = 0; i < n; i++) {
			cy += s_dy[dir]; cx += s_dx[dir];//이동
			if (cy == 0 && cx == 0) {
				cx = 999;
				break;
			}
			if (board[cy][cx] != 0) {//숫자 저장
				num.push_back(board[cy][cx]);
				board[cy][cx] = 0;//초기화
			}
		}
		if (cx == 999)break;
		dir++; if (dir == 4)dir = 0;//방향 변경
		cnt++;
		if (cnt == 2) {
			n++;
			cnt = 0;//리셋
		}
	}
	while (1) {
		int flag = 0;//종료 플래그
		for (int i = 0; i < num.size(); i++) {
			if (num.size() == 0)break;
			int cnt = 1;
			for (int j = i + 1; j < num.size(); j++) {
				if (num[i] == num[j])cnt++;
				else break;
			}
			if (cnt >= 4) {//4개 이상인경우 지우기
				flag = 1;
				if (num[i] == 1)ret1 += cnt;
				if (num[i] == 2)ret2 += cnt;
				if (num[i] == 3)ret3 += cnt;
				num.erase(num.begin() + i, num.begin() + i + cnt);//지우기
				i--;
			}
		}
		if (flag == 0)break;
	}

	vector<int>num2;//증가하는거 저장
	for (int i = 0; i < num.size(); i++) {
		while (1) {
			int flag = 0;//종료 플래그
			for (int i = 0; i < num.size(); i++) {
				if (num.size() == 0)break;
				int cnt = 1;
				for (int j = i + 1; j < num.size(); j++) {
					if (num[i] == num[j])cnt++;
					else break;
				}
				 num2.push_back(cnt); num2.push_back(num[i]);//증가하는것 저장 1 1 -> 2 1 로 저장
					num.erase(num.begin() + i, num.begin() + i + cnt);//지우기
					i--;
			}
			if (flag == 0)break;
		}
	}


	//다시 원위치
	 cy = N / 2;  cx = cy;//센터값
	 dir = 0;
	 n = 1;
	 cnt = 0;//두번 주기로 변경
	while (1) {
		for (int i = 0; i < n; i++) {
			cy += s_dy[dir]; cx += s_dx[dir];//이동
			if (num2.size()==0) {
				cx= 999;//탈출조건
				break;
			}
			board[cy][cx] = num2[0];
			num2.erase(num2.begin());
			if (cy == 0 && cx == 0) {
				cx = 999;
				break;
			}
		}
		if (cx == 999)break;
		dir++; if (dir == 4)dir = 0;//방향 변경
		cnt++;
		if (cnt == 2) {
			n++;
			cnt = 0;//리셋
		}
	}
	//증가하는 부분
	num.clear();
	num2.clear();
	
}
void simulation() {
	for (int m = 0; m < M; m++) {//동작 시작
		int dir, s;//마법 방향, 거리
		scanf("%d %d", &dir, &s);
		fire(dir,s);
	}
}

코드자체를 마법 별로 나누지 않아서 헷갈릴수 있다 추후에 정리해서 재정의 할것이긴  하지만 그래도 정답을 비교시 참고 해주세요. 

728x90
반응형

댓글