728x90
🧪 17090 미로 탈출하기
난이도 : 🌟 골드 3
유형 : BackTracking (DFS)
17090번: 미로 탈출하기
크기가 N×M인 미로가 있고, 미로는 크기가 1×1인 칸으로 나누어져 있다. 미로의 각 칸에는 문자가 하나 적혀있는데, 적혀있는 문자에 따라서 다른 칸으로 이동할 수 있다. 어떤 칸(r, c)에 적힌 문
www.acmicpc.net
📝 문제

크기가 N×M인 미로가 있고, 미로는 크기가 1×1인 칸으로 나누어져 있다. 미로의 각 칸에는 문자가 하나 적혀있는데, 적혀있는 문자에 따라서 다른 칸으로 이동할 수 있다.
어떤 칸(r, c)에 적힌 문자가
- U인 경우에는 (r-1, c)로 이동해야 한다.
- R인 경우에는 (r, c+1)로 이동해야 한다.
- D인 경우에는 (r+1, c)로 이동해야 한다.
- L인 경우에는 (r, c-1)로 이동해야 한다.
미로에서 탈출 가능한 칸의 수를 계산해보자. 탈출 가능한 칸이란, 그 칸에서 이동을 시작해서 칸에 적힌대로 이동했을 때, 미로의 경계 밖으로 이동하게 되는 칸을 의미한다.
입력
첫째 줄에 미로의 크기 N, M(3 ≤ N, M ≤ 500)이 주어진다. 둘째 줄부터 N개의 줄에는 미로의 각 칸에 적힌 문자가 주어진다.
출력
첫째 줄에 탈출 가능한 칸의 수를 출력한다.
🚧 주의할 점
1. dfs로만 접근하게 된다면 시간초과가 발생한다 → 백트래킹으로 모든 해를 검사하지 않고 탈출하는 경로 기록을 통해 더 빠르게 탈출할 수 있도록 한다.
실행초과 코드
import java.io.*;
import java.util.*;
public class Main {
static int n, m, cnt;
static char[][] maze;
static boolean[][] visited;
static int[] dx = {-1,1,0,0};
static int[] dy = {0,0,-1,1};
public static void main(String[] args) throws IOException {
// BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedReader br = new BufferedReader(new FileReader("input.txt"));
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
maze = new char[n][m];
for (int i = 0; i < n; i++) {
String word = br.readLine();
for (int j = 0; j < m; j++) {
maze[i][j] = word.charAt(j);
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
visited = new boolean[n][m];
dfs(maze[i][j], i, j);
}
}
System.out.println(cnt);
br.close();
}
private static void dfs(char dir, int x, int y) {
visited[x][y] = true;
int nx = x + dx[dirIndex(dir)];
int ny = y + dy[dirIndex(dir)];
if (nx < 0 || nx >= n || ny < 0 || ny >= m) {
cnt++;
return;
}
if (!visited[nx][ny]) {
dfs(maze[nx][ny], nx, ny);
}
}
private static int dirIndex(char dir) {
if (dir == 'D') {
return 1;
} else if (dir == 'U') {
return 0;
} else if (dir == 'L') {
return 2;
} else {
return 3;
}
}
}
🧐 핵심 로직
- 탈출 혹은 탈출했던 경로인 경우
- 탈출 시 거쳐간 경로 기록
- 탈출 가능 카운트 올리기
- 방문처리된 경로를 만난 경우
- 방문 처리가 되어있는데 1번을 거쳐왔다는 의미는 탈출이 불가능한 경로라는 의미이기 때문에 탈출 불가
- 탈출 시 거쳐간 모든 경로 true 기록
💻 최종 코드 (256 ms)
import java.io.*;
import java.util.*;
public class Main {
static int n, m, cnt;
static char[][] maze;
static boolean[][] visited, depth;
static int[] dx = {-1,1,0,0};
static int[] dy = {0,0,-1,1};
public static void main(String[] args) throws IOException {
// BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedReader br = new BufferedReader(new FileReader("input.txt"));
StringTokenizer st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
maze = new char[n][m];
visited = new boolean[n][m];
depth = new boolean[n][m];
for (int i = 0; i < n; i++) {
String word = br.readLine();
for (int j = 0; j < m; j++) {
maze[i][j] = word.charAt(j);
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
backTracking(maze[i][j], i, j);
}
}
System.out.println(cnt);
br.close();
}
private static boolean backTracking(char dir, int x, int y) {
visited[x][y] = true;
int nx = x + dx[dirIndex(dir)];
int ny = y + dy[dirIndex(dir)];
if ((nx < 0 || nx >= n || ny < 0 || ny >= m) || depth[nx][ny]) {
depth[x][y] = true;
cnt++;
return true;
}
if (visited[nx][ny]) {
return false;
}
return depth[x][y] = backTracking(maze[nx][ny], nx, ny);
}
private static int dirIndex(char dir) {
if (dir == 'D') {
return 1;
} else if (dir == 'U') {
return 0;
} else if (dir == 'L') {
return 2;
} else {
return 3;
}
}
}
'Hub Algorithm > BackTracking' 카테고리의 다른 글
[소프티어] LV3 : 함께하는 효도 (java) (0) | 2024.03.21 |
---|---|
[BOJ] 백준 3109 : 빵집 (java) (0) | 2024.02.21 |