Sliver
문제
N×M크기의 배열로 표현되는 미로가 있다.
1 | 0 | 1 | 1 | 1 | 1 |
1 | 0 | 1 | 0 | 1 | 0 |
1 | 0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 0 | 1 | 1 |
미로에서 1은 이동할 수 있는 칸을 나타내고, 0은 이동할 수 없는 칸을 나타낸다. 이러한 미로가 주어졌을 때, (1, 1)에서 출발하여 (N, M)의 위치로 이동할 때 지나야 하는 최소의 칸 수를 구하는 프로그램을 작성하시오. 한 칸에서 다른 칸으로 이동할 때, 서로 인접한 칸으로만 이동할 수 있다.
위의 예에서는 15칸을 지나야 (N, M)의 위치로 이동할 수 있다. 칸을 셀 때에는 시작 위치와 도착 위치도 포함한다.
입력
첫째 줄에 두 정수 N, M(2 ≤ N, M ≤ 100)이 주어진다. 다음 N개의 줄에는 M개의 정수로 미로가 주어진다. 각각의 수들은 붙어서 입력으로 주어진다.
출력
첫째 줄에 지나야 하는 최소의 칸 수를 출력한다. 항상 도착위치로 이동할 수 있는 경우만 입력으로 주어진다.
풀이_BFS
import java.util.*;
import java.io.*;
class Main {
static int[][] map;
static boolean[][] visited;
static int[] dx = {1, 0, -1, 0};
static int[] dy = {0, 1, 0, -1};
static int N, M;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
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 str = br.readLine();
for(int j=0; j<M; j++){
if(str.charAt(j) == '1') map[i][j] = 1;
}
}
visited[0][0] = true;
bfs(0, 0);
System.out.println(map[N-1][M-1]);
br.close();
}
public static void bfs(int x, int y){
Queue<int[]> q = new LinkedList<>();
q.offer(new int[] {x, y});
while(!q.isEmpty()){
int[] newnode = q.poll();
int qx = newnode[0];
int qy = newnode[1];
for(int i=0; i<4; i++){
int xx = qx + dx[i];
int yy = qy + dy[i];
if(xx>=0 && xx<N && yy>=0 && yy<M && !visited[xx][yy] && map[xx][yy]!=0){
visited[xx][yy] = true;
map[xx][yy] = map[qx][qy] + 1;
q.offer(new int[] {xx, yy});
}
}
}
}
}
해결방법
- 입력받은 값을 map에 저장한다. 이 때 방문을 체크하기 위해 같은 크기의 boolean배열 visited를 생성한다.
- 좌표가 {0, 0}인것부터 탐색을 시작한다.
- 현재 위치는 방문했으므로 visited를 true로 업데이트한다.
- 현재 위치에서 상하좌우 4방향을 탐색하고, 값이 0이 아니고 방문한 적이 없을 경우 현재 위치를 이동시킨다.
- 이동할 때마다 현재 칸의 값을 이전값 + 1 로 업데이트하고, 방문 배열도 업데이트한다
-> map[xx][yy] = map[qx][qy] + 1;
-> visited[xx][yy] = true;
- Queue 빌 때까지 반복한다.
- 도착점에 저장된 값이 최단 경로를 나타내므로 이를 출력한다. map[N-1][M-1]
미로찾기의 경우 DFS로는 문제를 통과할 수 없다.
이는 BFS는 최단경로를 보장하지만 DFS는 최단경로를 보장하지 않기 때문이다.
BFS와 DFS의 차이
- BFS : 너비를 우선으로 탐색하며, 시작점에서 가까운 좌표부터 차례대로 탐색하여 최단 경로를 보장한다. BFS는 경로를 하나씩 넓혀가며 가장 먼저 도착한 경로가 최단 경로이다.
- DFS : 깊이 우선 탐색으로, 한 경로를 끝까지 탐색한 후 다시 돌아와 다른 경로를 탐색하며 최단 경로를 보장하지 못할 수 있다. DFS는 미로의 경로를 깊이 우선으로 탐색하면서 더 긴 경로를 먼저 탐색할 가능성이 크다.
https://www.acmicpc.net/problem/2178
'Algorithm > Baekjoon Oline Judge - Java' 카테고리의 다른 글
[백준] 1260_DFS와 BFS / DFS, BFS (0) | 2024.10.19 |
---|---|
[백준] 2667_단지번호붙이기 / DFS, BFS (0) | 2024.09.22 |
[백준] 1012_유기농배추 / DFS, BFS, 상하좌우탐색 (0) | 2024.09.18 |
[백준] 2606_바이러스 / DFS 그래프 (1) | 2024.09.17 |
[백준] 1051_숫자정사각형 (0) | 2024.09.17 |