메이즈 러너 [2023-상반기 오후 1번 문제]

문제 링크

삼성 코딩테스트 기출 문제: 메이즈 러너 - 코드트리
주요 IT 기업의 코딩테스트 기출 문제를 연습하며 실전 감각을 키우세요. 취업 합격률을 높이는 필수 연습 과정입니다.

문제 설명

M명의 참가자가 미로를 탈출해야 함. N*N크기의 격자이고, 빈칸, 벽, 출구로 구분되어 있음.

1초마다 참가자는 한 칸씩 움직임. 움직이는 거리는 최단거리 abs(x1-x2) + abs(y1-y2) 로 움직임. 벽이 없는 곳으로 움직일 수 있고, 현재 머물러 있던 칸보다 최단거리가 가까워야 함. 움직일 수 있는 칸이 2칸 이상이라면, 상하로 움직이는 것을 선호함. 움직일 수 없으면, 움직이지 않음.

모든 참가자가 이동을 끝냈으면, 미로가 90도 회전함. 한 명 이상의 참가자와 출구를 포함한 가장 작은 정사각형을 잡음. 가장 작은 크기를 같은 정사각형이 2개 이상이라면 행-열 순으로 좌표가 작은 것이 우선시됨.

K초 동안 위의 과정이 반복되고, K초 전에 모든 참가자가 탈출을 성공한다면, 게임이 끝남. 모든 참가자들의 이동 거리의 합과 출구 좌표 출력

해결 방법

  1. 참가자들 움직임현재 위치보다 더 작은 값으로 이동 할 수 있는 값이 있다면, 해당 위치로 이동. 해당 위치가 출구라면 해당 참가자가 탈출했음을 표시.
for (int r = 0;r < m;r++) {
	if (runner[r].escaped) continue;
	int d = -1;
	int cur_d = get_distance(runner[r].x,runner[r].y);
	for (int i = 0;i < 4;i++) {
		int nx, ny;
		nx = runner[r].x + dx[i], ny = runner[r].y + dy[i];
		if (nx < 0 || ny < 0 || nx >= n || ny >= n) continue;
		if (arr[nx][ny]) continue;
		if (cur_d > get_distance(nx, ny)) {
			cur_d = get_distance(nx, ny);
			d = i;
		}
	}
	if (d == -1) continue;
//		if (arr[runner[r].x + dx[d]][runner[r].y + dy[d]]) continue;
	runner[r].x += dx[d], runner[r].y += dy[d];
	if (runner[r].x == ex && runner[r].y == ey) {
		runner[r].escaped = true;
		runner_cnt--;
		if (runner_cnt == 0) {
			move_cnt++;
			return;
		}
	}
	move_cnt++;
}
  1. 미로 회전미로가 회전해야 하는 좌상단, 그리고 길이를 찾음.
int lx, ly;
bool can_break = false;
int ssx, ssy, eex, eey;
for (int p = 1;p < n;p++) {
	for (int i = 0;i < n;i++) {
		for (int j = 0;j < n;j++) {
			lx = i + 1 * p; ly = j + 1 * p;
			if (lx < 0 || ly < 0 || lx >= n || ly >= n) continue;
			if (contains_runner_escape(i, j, p)) {
				can_break = true;
				ssx = i, ssy = j, eex = lx, eey = ly;
				break;
			}
		}
		if (can_break) break;
	}
	if (can_break) break;
}

그리고 미로를 회전시켜줌.

int tmp[11][11];

void rotate(int len) {
	int ttmp[11][11];

	for (int i = 0;i < len;i++) {
		for (int j = 0;j < len;j++) {
			ttmp[i][j] = tmp[len - j - 1][i];
		}
	}

	for (int i = 0;i < len;i++) {
		for (int j = 0;j < len;j++) {
			tmp[i][j] = ttmp[i][j];
		}
	}
}

void rotate_square(int sx,int sy,int lx, int ly) {
	memset(tmp, 0, sizeof(tmp));
	int len = abs(sx - lx) + 1;

	for (int i = 0;i < len;i++) {
		for (int j = 0;j < len;j++) {
			tmp[i][j] = arr[i+sx][j+sy];
		}
	}
	rotate(len);
	for (int i = 0;i < len;i++) {
		for (int j = 0;j < len;j++) {			
			arr[i + sx][j + sy] = tmp[i][j];
			if (arr[i + sx][j + sy] > 0) arr[i + sx][j + sy]--;
		}
	}

	memset(tmp, 0, sizeof(tmp));
	for (int i = 0;i < len;i++) {
		for (int j = 0;j < len;j++) {
			tmp[i][j] = runner_map[i + sx][j + sy];
		}
	}
	rotate(len);
	for (int i = 0;i < len;i++) {
		for (int j = 0;j < len;j++) {
			runner_map[i + sx][j + sy] = tmp[i][j];
		}
	}

	for (int i = 0;i < len;i++) {
		for (int j = 0;j < len;j++) {
			for (int k = 0;k < m;k++) {
				if (runner[k].cur == runner_map[i + sx][j + sy]) {
					runner[k].x = i + sx, runner[k].y = j + sy;
				}
				else if (runner_map[i + sx][j + sy] == -1) {
					ex = i + sx, ey = j + sy;
				}
			}
		}
	}
}

전체 코드

#include <iostream>
#include <cstring>
#include <queue>
#include <tuple>
using namespace std;

typedef struct {
	int x, y;
	int cur;
	bool escaped;
}_loc;

int n, m, k;
int ex, ey;
int arr[11][11];
int runner_map[11][11];
int runner_cnt;
_loc runner[11];
void input() {
	cin >> n >> m >> k;

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

	for (int i = 0;i < m;i++) {
		cin >> runner[i].x >> runner[i].y;
		runner[i].x--, runner[i].y--;
		runner[i].escaped = false;
	}

	runner_cnt = m;

	
	cin >> ex >> ey;
	ex--, ey--;
}

int dx[4] = { -1,1, 0,0 };
int dy[4] = { 0, 0, 1, -1 };

int visited[11][11];
_loc parent[11][11];

void set_runner_map() {
	memset(runner_map, 0, sizeof(runner_map));
	for (int i = 0;i < m;i++) {
		if (runner[i].escaped) continue;
		if (runner_map[runner[i].x][runner[i].y] == 0) {
			runner_map[runner[i].x][runner[i].y] = i + 1;
			runner[i].cur = i + 1;
		}
		else {
			runner[i].cur = runner_map[runner[i].x][runner[i].y];
		}
	}

	runner_map[ex][ey] = -1;
}

void print_arr() {
	int tmp_arr[11][11];
	memset(tmp_arr, 0, sizeof(tmp_arr));
	for (int i = 0;i < m;i++) {
		if (runner[i].escaped) continue;
		tmp_arr[runner[i].x][runner[i].y] = 1;
	}

	cout << "print_arr:\\n";
	for (int i = 0;i < n;i++) {
		for (int j = 0;j < n;j++) {
			if (tmp_arr[i][j]) cout << "# ";
			else if (i == ex && j == ey) cout << "@ ";
			else cout << arr[i][j] << " ";
		}
		cout << "\\n";
	}
	cout << "\\n";
}

int get_distance(int x, int y) {
	return abs(x - ex) + abs(y - ey);
}

bool contains_runner_escape(int sx,int sy,int p) {
	bool can_escape = false;
	bool can_runner = false;
	int cx, cy;
	for (int i = 0;i <= p;i++) {
		for (int j = 0;j <= p;j++) {
			cx = i + sx, cy = j + sy;
			if (cx == ex && cy == ey) can_escape = true;
			if (runner_map[cx][cy] && runner_map[cx][cy] != -1) {
				can_runner = true;
			}
		}
	}
	
	if (can_escape && can_runner) return true;
	return false;
}
int tmp[11][11];

void rotate(int len) {
	int ttmp[11][11];

	for (int i = 0;i < len;i++) {
		for (int j = 0;j < len;j++) {
			ttmp[i][j] = tmp[len - j - 1][i];
		}
	}

	for (int i = 0;i < len;i++) {
		for (int j = 0;j < len;j++) {
			tmp[i][j] = ttmp[i][j];
		}
	}
}

void rotate_square(int sx,int sy,int lx, int ly) {
	memset(tmp, 0, sizeof(tmp));
	int len = abs(sx - lx) + 1;

	for (int i = 0;i < len;i++) {
		for (int j = 0;j < len;j++) {
			tmp[i][j] = arr[i+sx][j+sy];
		}
	}
	rotate(len);
	for (int i = 0;i < len;i++) {
		for (int j = 0;j < len;j++) {			
			arr[i + sx][j + sy] = tmp[i][j];
			if (arr[i + sx][j + sy] > 0) arr[i + sx][j + sy]--;
		}
	}

	memset(tmp, 0, sizeof(tmp));
	for (int i = 0;i < len;i++) {
		for (int j = 0;j < len;j++) {
			tmp[i][j] = runner_map[i + sx][j + sy];
		}
	}
	rotate(len);
	for (int i = 0;i < len;i++) {
		for (int j = 0;j < len;j++) {
			runner_map[i + sx][j + sy] = tmp[i][j];
		}
	}

	for (int i = 0;i < len;i++) {
		for (int j = 0;j < len;j++) {
			for (int k = 0;k < m;k++) {
				if (runner[k].cur == runner_map[i + sx][j + sy]) {
					runner[k].x = i + sx, runner[k].y = j + sy;
				}
				else if (runner_map[i + sx][j + sy] == -1) {
					ex = i + sx, ey = j + sy;
				}
			}
		}
	}
}

int move_cnt = 0;

void solve(int t) {
	// 1. 참가자 움직임
	for (int r = 0;r < m;r++) {
		if (runner[r].escaped) continue;
		int d = -1;
		int cur_d = get_distance(runner[r].x,runner[r].y);
		for (int i = 0;i < 4;i++) {
			int nx, ny;
			nx = runner[r].x + dx[i], ny = runner[r].y + dy[i];
			if (nx < 0 || ny < 0 || nx >= n || ny >= n) continue;
			if (arr[nx][ny]) continue;
			if (cur_d > get_distance(nx, ny)) {
				cur_d = get_distance(nx, ny);
				d = i;
			}
		}
		if (d == -1) continue;
//		if (arr[runner[r].x + dx[d]][runner[r].y + dy[d]]) continue;
		runner[r].x += dx[d], runner[r].y += dy[d];
		if (runner[r].x == ex && runner[r].y == ey) {
			runner[r].escaped = true;
			runner_cnt--;
			if (runner_cnt == 0) {
				move_cnt++;
				return;
			}
		}
		move_cnt++;
	}
	set_runner_map();
	// 2. 미로 회전
	int lx, ly;
	bool can_break = false;
	int ssx, ssy, eex, eey;
	for (int p = 1;p < n;p++) {
		for (int i = 0;i < n;i++) {
			for (int j = 0;j < n;j++) {
				lx = i + 1 * p; ly = j + 1 * p;
				if (lx < 0 || ly < 0 || lx >= n || ly >= n) continue;
				if (contains_runner_escape(i, j, p)) {
					can_break = true;
					ssx = i, ssy = j, eex = lx, eey = ly;
					break;
				}
			}
			if (can_break) break;
		}
		if (can_break) break;
	}
	if (!can_break) {
		cout << "error!\\n";
		print_arr();
		exit(0);
	}
	rotate_square(ssx,ssy,eex,eey);
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
//	freopen("sample_input.txt", "r", stdin);
	input();
//	print_arr();
	for (int i = 0;i < k;i++) {
		solve(i);
//		print_arr();
		if (runner_cnt == 0) break;
	}
	cout << move_cnt << "\\n" << ex + 1 << " " << ey + 1;
}