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

어른 상어 C++

by paysmile 2021. 3. 4.

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

 

19237번: 어른 상어

첫 줄에는 N, M, k가 주어진다. (2 ≤ N ≤ 20, 2 ≤ M ≤ N2, 1 ≤ k ≤ 1,000) 그 다음 줄부터 N개의 줄에 걸쳐 격자의 모습이 주어진다. 0은 빈칸이고, 0이 아닌 수 x는 x번 상어가 들어있는 칸을 의미

www.acmicpc.net

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;
const int MAX = 21;
int n, m, K;
struct value { int who, smell, exist; };
value map[MAX][MAX];
struct MOVE { int x, y; };
//1:위 2:아래 3:왼쪽 4:오른쪽
MOVE mv[5] = { { 0,0 },{ -1,0 },{ 1,0 },{ 0,-1 },{ 0,1 } };

struct shark { int num, x, y, dir; };
vector<shark> s;
int pri[500][5][5];

int answer = 0;
vector<shark> temp;

bool cmp(shark a, shark b) {
	return  a.num < b.num;
}

bool CheckLeft() {
	if (s.size() == 1)
		return true;
	else
		return false;
}
void MoveShark()
{
	temp.clear();

	for (int i = 0; i < s.size(); i++) {
		int flag = false;
		int priority_dir;
		//비어있는 칸
		for (int k = 0; k < 4; k++) {
			priority_dir = pri[s[i].num][s[i].dir][k];
			int movei = s[i].x + mv[priority_dir].x;
			int movej = s[i].y + mv[priority_dir].y;
			if (movei > 0 && movei <= n && movej > 0 && movej <= n) {
				if (map[movei][movej].smell == 0) {
					temp.push_back({ s[i].num,movei,movej,priority_dir });
					flag = true;
					break;
				}
			}
		}
		//내 냄새가 나는 칸
		if (flag == false) {
			for (int k = 0; k < 4; k++) {
				priority_dir = pri[s[i].num][s[i].dir][k];
				int movei = s[i].x + mv[priority_dir].x;
				int movej = s[i].y + mv[priority_dir].y;
				if (movei > 0 && movei <= n && movej > 0 && movej <= n) {
					if (map[movei][movej].who == s[i].num) {
						temp.push_back({ s[i].num,movei,movej,priority_dir });
						flag = true;
						break;
					}
				}
			}
		}
		if (flag == false)
			temp.push_back({ s[i].num,s[i].x,s[i].y,s[i].dir });
	}
}
void MoveShark2() {
	for (int i = 0; i < temp.size(); i++) {
		if (map[temp[i].x][temp[i].y].exist == 1) {
			//상어 삭제
			temp.erase(temp.begin() + i);
			i -= 1;
		}
		else {
			map[temp[i].x][temp[i].y].exist = 1;
			map[temp[i].x][temp[i].y].who = temp[i].num;
			map[temp[i].x][temp[i].y].smell = K;
		}
	}
	s.clear();
	s = temp;
}
void ReduceSmell() {
	//방금까지 상어가 있었던 자리 없어진 걸로 변경
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			if (map[i][j].smell >0)
				map[i][j].smell -= 1;
			if (map[i][j].smell == 0) {
				map[i][j].who = 0;
			}
			map[i][j].exist = 0;
		}
	}
}

int main(void) {
	int finish = false;

	cin >> n >> m >> K;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			int v;
			cin >> v;
			if (v == 0)
				map[i][j] = { 0,0,0 };
			else if (v != 0) {
				s.push_back({ v,i,j,0 });
				map[i][j] = { v,K,1 };
			}
		}
	}

	sort(s.begin(), s.end(), cmp);

	for (int i = 0; i < m; i++) {
		cin >> s[i].dir;
	}

	for (int i = 0; i < m; i++) {
		for (int j = 0; j < 4; j++) {
			cin >> pri[s[i].num][j + 1][0] >> pri[s[i].num][j + 1][1] >> pri[s[i].num][j + 1][2] >> pri[s[i].num][j + 1][3];
		}
	}

	while (answer < 1000) {
		MoveShark();
		ReduceSmell();
		MoveShark2();
		answer++;
		if (CheckLeft()) {
			finish = true;
			break;
		}
	}
	if (finish == true)
		cout << answer;
	else cout << -1;

	return 0;
}

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

주사위 윷놀이 C++  (0) 2021.03.10
모노미노도미노 2  (0) 2021.03.08
컨베이어 벨트 위의 로봇 C++  (0) 2021.03.01
마법사 상어와 토네이도  (0) 2021.02.22
마법사 상어와 파이어볼 C++  (0) 2021.02.18