16954 움직이는 미로 탈출
https://www.acmicpc.net/problem/16954
문제설명
캐릭터가 벽이 이동하는 가운데 목표 위치로 이동할 수 있는지 계산
접근방식
O(1) 상수 시간복잡도
체스판의 크기가 고정되어 있으며, BFS 탐색과 벽 이동 처리 모두 상수 시간 내에 처리된다.
문제 조건 분석 과정
- 체스판 크기: 8x8 (고정 크기)
- 캐릭터 이동: 인접한 8 방향 또는 대각선으로 이동 가능
- 벽 이동: 벽은 매 초마다 아래로 한 칸 이동
매 초마다 벽을 아래로 한 칸 이동시키며, 벽이 사라지면 새로운 벽이 추가된다.
- 캐릭터의 위치를 BFS(너비 우선 탐색)를 사용하여 탐색한다.
- BFS는 현재 위치에서 인접한 모든 위치를 탐색하며 이동한다.
전체코드
import java.util.*;
import java.io.*;
public class Main {
// 상하좌우 이동을 위한 방향 배열
static final int[] dx = {1, -1, 0, 0};
static final int[] dy = {0, 0, 1, -1};
// 말의 L자 이동을 위한 방향 배열
static final int[] horseDx = {2, 2, -2, -2, 1, 1, -1, -1};
static final int[] horseDy = {1, -1, 1, -1, 2, -2, 2, -2};
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 첫 번째 줄에서 K 값을 읽어옴 (원숭이의 말과 같은 L자 이동 횟수)
StringTokenizer st = new StringTokenizer(br.readLine());
int K = Integer.parseInt(st.nextToken());
// 두 번째 줄에서 W와 H 값을 읽어옴 (그리드의 너비와 높이)
st = new StringTokenizer(br.readLine());
int W = Integer.parseInt(st.nextToken());
int H = Integer.parseInt(st.nextToken());
// H x W 크기의 그리드를 읽어옴
int[][] grid = new int[H][W];
for (int i = 0; i < H; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < W; j++) {
grid[i][j] = Integer.parseInt(st.nextToken());
}
}
// visited 배열을 초기화 (방문 여부와 최단 거리를 저장)
// visited[x][y][k]는 좌표 (x, y)에 말과 같은 L자 이동이 k번 남았을 때의 최단 거리
int[][][] visited = new int[H][W][K + 1];
for (int[][] row : visited) {
for (int[] cell : row) {
Arrays.fill(cell, -1);
}
}
// BFS 탐색을 위한 큐
Queue<int[]> queue = new LinkedList<>();
// 시작점 (0, 0), 말과 같은 L자 이동 횟수 K, 현재 이동 거리 0
queue.add(new int[]{0, 0, K, 0});
visited[0][0][K] = 0;
// BFS 탐색 시작
while (!queue.isEmpty()) {
int[] current = queue.poll();
int x = current[0]; // 현재 x 좌표
int y = current[1]; // 현재 y 좌표
int remainingHorseMoves = current[2]; // 남은 말과 같은 L자 이동 횟수
int moves = current[3]; // 현재까지 이동한 거리
// 목표 지점에 도착하면 최단 거리 출력
if (x == H - 1 && y == W - 1) {
System.out.println(moves);
return;
}
// 상하좌우 이동
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
// 이동 가능한 위치인지 확인
if (nx >= 0 && ny >= 0 && nx < H && ny < W && grid[nx][ny] == 0 && visited[nx][ny][remainingHorseMoves] == -1) {
visited[nx][ny][remainingHorseMoves] = moves + 1;
queue.add(new int[]{nx, ny, remainingHorseMoves, moves + 1});
}
}
// 남아 있는 말과 같은 L자 이동 횟수가 있는 경우
if (remainingHorseMoves > 0) {
// 말의 이동을 적용하여 새로운 위치 탐색
for (int i = 0; i < 8; i++) {
int nx = x + horseDx[i];
int ny = y + horseDy[i];
// 이동 가능한 위치인지 확인
if (nx >= 0 && ny >= 0 && nx < H && ny < W && grid[nx][ny] == 0 && visited[nx][ny][remainingHorseMoves - 1] == -1) {
visited[nx][ny][remainingHorseMoves - 1] = moves + 1;
queue.add(new int[]{nx, ny, remainingHorseMoves - 1, moves + 1});
}
}
}
}
// 목표 지점에 도달할 수 없는 경우 -1 출력
System.out.println(-1);
}
}
'자료구조 > 문제풀이' 카테고리의 다른 글
[백준 JAVA] 7562 나이트의 이동 (0) | 2024.08.24 |
---|---|
[백준 JAVA] 2146 다리 만들기 (0) | 2024.08.24 |
[백준 JAVA] 1743 음식물 피하기 (0) | 2024.08.23 |
[백준 JAVA] 1991 트리 순회 (0) | 2024.08.23 |
[백준 JAVA] 13023 ABCDE (0) | 2024.08.22 |