[BOJ 2178] 미로 탐색
업데이트:
문제
- BOJ 2178
- 문제의 저작권은 Baekjoon Online Judge에 있습니다.
접근방식
처음에 아무 의심없이 DFS로 풀었다가 1시간 이상 시간초과로 삽질한 문제이다..
이 문제에서 요구하는 것은 최단 거리이므로 DFS를 사용해서 풀면 모든 경로의 경우의 수를 탐색하므로 시간초과가 발생한다.
그러나 BFS로 풀게되면 입력 조건이 항상 마지막 N,M좌표에 도착하므로 결국 마지막 좌표값이 무조건 최단거리가 된다.
- 큐에 시작좌표
(1,1)
과 칸의 개수1
을 넣는다. - 큐가 빌때까지(=마지막 좌표에 올때까지) 다음을 반복한다.
2-1. 큐에서 하나 꺼내 4방향 탐색으로 다음 좌표를 구한다.
2-2. 다음 좌표값이 1)범위안이고 2)배열값이 0이 아니고 3)아직 방문하지 않았다면 현재 까지 온 칸수에 1을 더해 배열값을 변경해주고 방문처리 후 큐에 넣어준다.
[주의] 여기서 방문처리하지 않으면 큐에 있는 다른 좌표에 의해 큐에 중복 삽입될 수 있으므로 메모리 초과가 발생함. while문
이 종료되면 탐색이 종료되었으므로 마지막 좌표의 배열값을 출력해주면 그 값이 최단 거리가 된다.
그래도 DFS,BFS는 잘 안다고 생각했는데 반성하게 되는 문제였다 ㅠㅠ
import java.io.*;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
//dfs로 푸니 시간초과남 => 최단거리일때는 bfs 사용하기
public class Main {
static int N, M;
static int[][] map;
static boolean[][] visited; //방문 기록
static int[] di = {-1, 1, 0, 0}; //상하좌우
static int[] dj = {0, 0, -1, 1};
static class Point {
int x;
int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
map = new int[N][M];
visited = new boolean[N][M];
for (int i = 0; i < N; i++) {
String s = br.readLine();
for (int j = 0; j < M; j++) {
map[i][j] = s.charAt(j) - '0';
}
}//End input
Queue<Point> queue = new LinkedList<>();
queue.add(new Point(0, 0));
map[0][0] = 1;
visited[0][0] = true;
while (!queue.isEmpty()) {
Point p = queue.poll();
for (int d = 0; d < 4; d++) {
int nx = p.x + di[d];
int ny = p.y + dj[d];
//현재까지 온 칸 수가 더 많거나 같을때만 큐에 넣기
if (nx >= 0 && nx < N && ny >= 0 && ny < M && map[nx][ny] != 0 && !visited[nx][ny]) {
map[nx][ny] = map[p.x][p.y] + 1; //현재까지 온 칸수 + 1
visited[nx][ny] = true; //방문처리
queue.add(new Point(nx, ny));
}
}//End 4방향 탐색
}//End BFS
System.out.println(map[N-1][M-1]);
}
}