기술 블로그

19237번 어른상어 본문

알고리즘 문제/BOJ

19237번 어른상어

parkit 2021. 2. 13. 00:37
728x90
반응형

www.acmicpc.net/problem/19237

 

 

 

 

 

 

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

#include <bits/stdc++.h>

using namespace std;

#define SHARK_MAX 1010
#define BOARD_MAX_SIZE 22

// 1:위, 2:아래, 3:왼, 4:오

// N:배열 크기, M:상어 수(1~M), K:시간
int N, M, K;
// 1~M번 상어의 위치(y, x)
pair<int, int> shark_position[SHARK_MAX];
// 냄새에 대한 정보 배열(상어 번호, 시간)
pair<int, int> smell[BOARD_MAX_SIZE][BOARD_MAX_SIZE];
// n번 상어의 현재 방향
int now_shark_direction[SHARK_MAX];
// n번 상어의 현재 방향에 따른 우선순위
vector<int> priority_direction[SHARK_MAX][5];
// 한 칸 이동하기 위한 변수
int dy[5] = { 0, -1, 1, 0, 0 };
int dx[5] = { 0, 0, 0, -1, 1 };
// 살아있는지(?) 변수
bool isLive[SHARK_MAX];
// 상어 위치 지도 및 임시 지도
int Map[BOARD_MAX_SIZE][BOARD_MAX_SIZE];
int temp[BOARD_MAX_SIZE][BOARD_MAX_SIZE];

bool chk()
{
	for (int i = 2; i <= M; i++) {
		if (isLive[i]) {
			return false;
		}
	}

	return true;
}

int simulation()
{
	for (int time = 1; time <= 1000; time++) {
		map<pair<int, int>, int> m;
		memset(temp, 0, sizeof(temp));

		for (int i = M; i >= 1; i--) {
			if (!isLive[i]) {
				continue;
			}

			// 상어 위치 및 현재 바라보고 있는 방향
			int r = shark_position[i].first;
			int c = shark_position[i].second;
			int now_direction = now_shark_direction[i];

			// 자신의 냄새가 있는 (이동할) 칸 위치 저장
			int sr = 0, sc = 0;

			bool isExistPd = false;

			// 우선순위 처리 표시
			bool temp_chk = false;
			int temp_pd = 0;

			// 상어의 현재 방향에 따른 우선순위 방향
			for (int pd : priority_direction[i][now_direction]) {
				int y = r + dy[pd];
				int x = c + dx[pd];

				if (y < 0 || y >= N || x < 0 || x >= N) {
					continue;
				}

				if (smell[y][x].first != NULL && smell[y][x].second != NULL) {
					if (!temp_chk && smell[y][x].first == i) {
						temp_chk = true;
						temp_pd = pd;
						sr = y;
						sc = x;
					}			
					continue;
				}

				// 갈 수 있는 방향 표시(냄새가 없는 칸)
				isExistPd = true;

				// 상어 위치 및 방향 갱신
				shark_position[i] = { y, x };
				now_shark_direction[i] = pd;

				if (temp[y][x] != 0) {
					isLive[temp[y][x]] = false;
				}

				temp[y][x] = i;

				break;
			}

			// 자신의 냄새가 있는 칸으로 이동
			if (!isExistPd) {
				if (temp[sr][sc] != 0) {
					isLive[temp[sr][sc]] = false;
				}
				temp[sr][sc] = i;
				shark_position[i] = { sr, sc };
				now_shark_direction[i] = temp_pd; // 이 부분을 실수.
			}
		}

		// 기존 냄새 시간 -1 감소
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				if (smell[i][j].first != NULL && smell[i][j].second != NULL) {
					// (상어 번호, 시간)
					if (--smell[i][j].second == 0) {
						smell[i][j] = { NULL, NULL };
					}
				}
			}
		}

		// 새로운 냄새 갱신
		for (int i = 1; i <= M; i++) {
			if (!isLive[i]) {
				continue;
			}

			int y = shark_position[i].first;
			int x = shark_position[i].second;

			smell[y][x].first = i;
			smell[y][x].second = K;
		}

		// 1번 상어만 격자에 남겨져 있는지 체크
		if (chk()) {
			return time;
		}
	}

	return -1;
}

void init()
{
	scanf("%d %d %d", &N, &M, &K);

	int init_input = 0;

	// 초기 상어 위치 정보
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			smell[i][j] = { NULL, NULL };
			
			scanf("%d", &init_input);
			Map[i][j] = init_input;

			if (init_input != 0) {
				shark_position[init_input] = { i, j };
				// 맨 처음에는 모든 상어가 자신의 위치에 자신의 냄새를 뿌린다.
				smell[i][j] = { init_input , K }; // {상어 번호, 시간}
				isLive[init_input] = true; // 살아있음 표시
			}
		}
	}

	// 각 상어의 초기 현재 방향
	for (int i = 1; i <= M; i++) {
		scanf("%d", &init_input);
		now_shark_direction[i] = init_input;
	}

	// 상어의 현재 방향에 따른 우선순위
	for (int i = 1; i <= M; i++) {
		for (int j = 1; j <= 4; j++) {
			for (int k = 1; k <= 4; k++) {
				scanf("%d", &init_input);
				priority_direction[i][j].push_back(init_input);
			}
		}
	}
}

int main()
{
	//freopen("C:\\Users\\park7\\Desktop\\buba.in.6", "r", stdin);
	cin.tie(0);

	init();
	
	printf("%d\n", simulation());

	return 0;
}

 

 

 

 

 

 

 

colorscripter.com/s/OSZjETB

 

공유된 코드 - Color Scripter

코드 설명 : https://www.acmicpc.net/problem/19237

colorscripter.com

 

 

 

 

 

109번 째 줄에서 실수를 했었는데 자신의 냄새가 있는 칸으로 이동하는 방향은 현재 자신의 방향에 대한 역방향이 아니다. 처음에는 현재 자신의 방향에 대한 역방향으로 무조건 저장했었다. 자신의 냄새가 있는 칸의 방향은 상하좌우 모두 될 수 있으므로, 우선순위 방향에 대한 for문에서도 따로 저장해야한다.

 

그리고 상어를 큰 번호부터 for문을 수행하면, 잡아 먹히는 과정에 대한 로직이 크게 감소한다.(덮어 씌우면 됨)

 

 

 

 

 

 

728x90
반응형

'알고리즘 문제 > BOJ' 카테고리의 다른 글

17485번 진우의 달 여행 (Large)  (3) 2021.03.20
1562번 계단수  (0) 2021.03.08
20055번 컨베이어 벨트 위의 로봇  (0) 2020.11.15
5525번 IOIOI  (0) 2020.06.23
12102번 종이 접기 2  (0) 2020.04.21