반응형
문제
- 문제 링크: 미로 탈출
해설
- 자료구조:
- 시간복잡도:
(풀이과정)
1)
2)
3)
4)
코드
(C언어)
solution 1)
더보기
solution 1
#include<>
solution 2)
더보기
#include<>
solution 3)
더보기
#include<>
(C++)
solution 1)
더보기
#include<>
solution 2)
더보기
#include<>
solution 3)
더보기
#include<>
(C#)
solution 1)
더보기
#include<>
solution 2)
더보기
#include<>
solution 3)
더보기
#include<>
(Java)
solution 1)
- N: 지도 한 변의 길이
- 이동 과정은 최악의 경우 지도의 크기가 N*N, 네 방향으로 이동하므로 시간 복잡도는 O(4*(N^2))
- 최종 시간 복잡도: O(N^2)
더보기
import java.util.ArrayDeque;
public class Solution {
// 위, 아래, 왼쪽, 오른쪽 이동 방향
private static final int[] dx = {0, 0, -1, 1};
private static final int[] dy = {-1, 1, 0, 0};
// 위치 정보(x, y)를 저장할 클래스 생성
private static class Point {
int nx, ny;
public Point(int nx, int ny) {
this.nx = nx;
this.ny = ny;
}
}
private static char[][] map;
private static int N, M;
public int solution(String[] maps) {
N = maps.length;
M = maps[0].length();
// 미로에 대한 정보를 배열로 저장
map = new char[N][M];
for (int i = 0; i < N; i++) {
map[i] = maps[i].toCharArray();
}
Point start = null, end = null, lever = null;
// 시작 지점, 출구 그리고 레버의 위치를 찾음
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (map[i][j] == 'S') start = new Point(j, i);
else if (map[i][j] == 'E') end = new Point(j, i);
else if (map[i][j] == 'L') lever = new Point(j, i);
}
}
// 시작 자점 -> 레버, 레버 -> 출구까지의 최단 거리를 각각 구함
int startLever = bfs(start, lever);
int leverEnd = bfs(lever, end);
// 도착 불가능한 경우는 -1, 도착 가능한 경우는 최단 거리를 반환
if (startLever == -1 || leverEnd == -1)
return -1;
else
return startLever + leverEnd;
}
// start -> end 로 너비 우선 탐색하여 최단거리 반환
private static int bfs(Point start, Point end) {
// 너비 우선 탐색 초기 과정
int[][] dist = new int[N][M];
ArrayDeque<Point> queue = new ArrayDeque<>();
dist[start.ny][start.nx] = 1;
queue.add(start);
while (!queue.isEmpty()) {
Point now = queue.poll();
// 네 방향으로 이동
for (int i = 0; i < 4; i++) {
int nextX = now.nx + dx[i];
int nextY = now.ny + dy[i];
// 범위를 벗어나는 경우 예외 처리
if (nextX < 0 || nextX >= M || nextY < 0 || nextY >= N)
continue;
// 이미 방문한 지점인 경우 탐색하지 않음
if (dist[nextY][nextX] > 0)
continue;
// X가 아닌 지점만 이동 가능
if (map[nextY][nextX] == 'X')
continue;
// 거리 1증가
dist[nextY][nextX] = dist[now.ny][now.nx] + 1;
// 다음 정점을 큐에 넣음
queue.add(new Point(nextX, nextY));
// 도착점에 도달하면 최단 거리를 반환
if (nextX == end.nx && nextY == end.ny)
return dist[end.ny][end.nx] - 1;
}
}
// 탐색을 종료할 때까지 도착 지점에 도달하지 못 했다면 -1 반환
return -1;
}
}
solution 2)
더보기
#include<>
solution 3)
더보기
#include<>
(Python)
solution 1)
- N: 지도 한 변의 길이
- is_valid_move()와 append_to_queue()의 시간 복잡도: O(1)
- 이동 과정은 최악의 경우 지도의 크기가 N*N, 네 방향으로 이동하므로 시간 복잡도: O(4*(N^2))
- 최종 시간 복잡도: O(N^2)
더보기
from collections import deque
# 이동 가능한 좌표인지 판단하는 함수
def is_valid_move(ny, nx, n, m, maps):
return 0 <= ny < n and 0 <= nx < m and maps[ny][nx] != "X"
# 방문한 적이 없으면 큐에 넣고 방문 여부 표시
def append_to_queue(ny, nx, k, time, visited, q):
if not visited[ny][nx][k]:
visited[ny][nx][k] = True
q.append((ny, nx, k, time + 1))
def solution(maps):
n, m = len(maps), len(maps[0])
visited = [[[False for _ in range(2)] for _ in range(m)] for _ in range(n)]
# 위, 아래, 왼쪽, 오른쪽 이동 방향
dy = [-1, 1, 0, 0]
dx = [0, 0, -1, 1]
q = deque()
end_y, end_x = -1, -1
# 시작점과 도착점을 찾아 큐에 넣고 방문 여부 표시
for i in range(n):
for j in range(m):
if maps[i][j] == "S":
q.append((i, j, 0, 0)) # 시작점
visited[i][j][0] = True
if maps[i][j] == "E":
end_y, end_x = i, j # 도착점
while q:
y, x, k, time = q.popleft() # 큐에서 좌표와 이동 횟수를 꺼냄
# 도착점에 도달하면 결과 반환
if y == end_y and x == end_x and k == 1:
return time
# 네 방향으로 이동
for i in range(4):
ny, nx = y + dy[i], x + dx[i]
# 이동 가능한 좌표인 때에만 큐에 넣음
if not is_valid_move(ny, nx, n, m, maps):
continue
# 다음 이동 지점이 물인 경우
if maps[ny][nx] == "L":
append_to_queue(ny, nx, 1, time, visited, q)
# 다음 이동 지점이 물이 아닌 경우
else:
append_to_queue(ny, nx, k, time, visited, q)
# 도착점에 도달하지 못한 경우
return -1
solution 2)
더보기
import
solution 3)
더보기
import
(JavaScript)
solution 1)
- N: 지도 한변의 길이
- isValidMove()와 appendToQueue(): O(1)
- 이동 과정은 최악의 경우 지도의 크기가 N*N, 네 방향으로 이동하므로 시간복잡도: O(4*(N^2))
- 최종 시간 복잡도: O(N^2)
더보기
class Queue {
items = [];
front = 0;
rear = 0;
push(item) {
this.items.push(item);
this.rear++;
}
pop() {
return this.items[this.front++];
}
isEmpty() {
return this.front === this.rear;
}
}
// 이동 가능한 좌표인지 판단하는 함수
function isValidMove(ny, nx, n, m, maps) {
return 0 <= ny && ny < n && 0 <= nx && nx < m && maps[ny][nx] !== 'X';
}
// 방문한 적이 없으면 큐에 넣고 방문 여부 표시
function appendToQueue(ny, nx, k, time, visited, q) {
if (!visited[ny][nx][k]) {
visited[ny][nx][k] = true;
q.push([ny, nx, k, time + 1]);
}
}
function solution(maps) {
const n = maps.length;
const m = maps[0].length;
const visited = Array.from(Array(n), () => Array(m).fill(false).map(() => Array(2).fill(false)));
// 위, 아래, 왼쪽, 오른쪽 이동 방향
const dy = [-1, 1, 0, 0];
const dx = [0, 0, -1, 1];
const q = new Queue();
let endY = -1;
let endX = -1;
// 시작점과 도착점을 찾아 큐에 넣고 방문 여부 표시
for (let i = 0; i < n; ++i) {
for (let j = 0; j < m; ++j) {
if (maps[i][j] === 'S') { // 시작점
q.push([i, j, 0, 0]);
visited[i][j][0] = true;
}
if (maps[i][j] === 'E') { // 도착점
endY = i;
endX = j;
}
}
}
while (!q.isEmpty()) {
const [y, x, k, time] = q.pop(); // 큐에서 좌표와 이동 횟수를 꺼냄
// 도착점에 도달하면 결과 반환
if (y === endY && x === endX && k === 1) {
return time;
}
// 네 방향으로 이동
for (let i = 0; i < 4; ++i) {
const ny = y + dy[i];
const nx = x + dx[i];
// 이동 가능한 좌표인 때에만 큐에 넣음
if (!isValidMove(ny, nx, n, m, maps)) {
continue;
}
// 다음 이동 지점이 레버인 경우
if (maps[ny][nx] === 'L') {
appendToQueue(ny, nx, 1, time, visited, q);
} else { // 다음 이동 지점이 레버가 아닌 경우
appendToQueue(ny, nx, k, time, visited, q);
}
}
}
// 도착점에 도달하지 못하는 경우
return -1;
}
solution 2)
더보기
import
solution 3)
더보기
import
반응형
'1-4. 코딩테스트 문제집(진행중) > PCCP(Lv2)' 카테고리의 다른 글
[PCCP] Lv2: 배달(12978) 해설 (0) | 2024.12.25 |
---|---|
[PCCP] Lv2: 게임 맵 최단거리(1844) 해설 (0) | 2024.12.25 |
[PCCP] Lv2: 예상 대진표(12985) 해설 (0) | 2024.12.24 |
[PCCP] Lv2: 메뉴 리뉴얼(72411) 해설 (0) | 2024.12.24 |
[PCCP] Lv2: 오픈 채팅방(42888) 해설 (0) | 2024.12.24 |