https://www.acmicpc.net/problem/2178
시간 제한 | 메모리 제한 | 제출 | 정답 | 맞은 사람 | 정답 비율 |
1 초 | 192MB | 99380 | 40148 | 25619 | 39.046% |
문제
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개의 정수로 미로가 주어진다. 각각의 수들은 붙어서 입력으로 주어진다.
출력
첫째 줄에 지나야 하는 최소의 칸 수를 출력한다. 항상 도착위치로 이동할 수 있는 경우만 입력으로 주어진다.
<풀이>
처음에는 DFS로 풀려고했는데, 재귀 방식으로 풀려면 최단 경로를 찾아야하기 때문에 사실상 모든 경로를 다 탐색해야했다. DFS가 아니라 브루트포스가 되어버림
그래서 DFS로는 못풀고, BFS로 풀어야 했다.
BFS를 사용하면 한 지점에서 연결된 모든 정점으로 이동할 때, 한 칸씩 이동되기 때문에 결국 BFS를 몇 번 수행했는지만 알면 어떠한 칸에 도달하기까지의 최단 거리를 손쉽게 구해낼 수 있다.
상하좌우로 이동할 수 있기 때문에 상하좌우의 이동방향을 배열에 저장하여 손쉽게 탐색을 이어나갈 수 있도록 하였다.
private static int[][] moving = { { -1, 0 }, { 0, -1 }, { 0, 1 }, { 1, 0 } };
그리고 이동하는 점의 좌표와 해당 정점에 오기까지 BFS를 몇 번 수행했는지 저장해야했기 때문에, BFS를 수행할 큐의 타입을 클래스를 만들어 지정해주었다.
class Coordinate {
int x = 0;
int y = 0;
int cnt = 0;
Coordinate(int x, int y, int cnt) {
this.x = x;
this.y = y;
this.cnt = cnt;
}
}
이를 이용하여 BFS를 수행하면 된다.
소스코드
import java.io.*;
import java.util.*;
public class Main {
private static int[][] moving = { { -1, 0 }, { 0, -1 }, { 0, 1 }, { 1, 0 } };
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
int[][] maze = new int[n][m];
boolean[][] check = new boolean[n][m];
// 미로 입력
for (int i = 0; i < n; i++) {
String s = br.readLine();
for (int j = 0; j < m; j++) {
maze[i][j] = s.charAt(j) - '0';
}
}
// 미로 탐색, 첫 번째 점(0,0)에서 시작
// 최단 거리 알고리즘이기 때문에 BFS를 이용
Queue<Coordinate> queue = new LinkedList<Coordinate>();
queue.add(new Coordinate(0, 0, 1));
check[0][0] = true;
while (!queue.isEmpty()) {
// 이어진 점이 있는지 검사
int x = queue.peek().x;
int y = queue.peek().y;
if (x == m - 1 && y == n - 1) {
System.out.println(queue.peek().cnt);
break;
}
for (int i = 0; i < 4; i++) {
int nx = x + moving[i][0];
int ny = y + moving[i][1];
if (nx >= 0 && ny >= 0 && nx < m && ny < n) {
if (maze[ny][nx] == 1 && !check[ny][nx]) {
check[ny][nx] = true;
queue.add(new Coordinate(nx, ny, queue.peek().cnt + 1));
}
}
}
queue.poll();
}
}
}
class Coordinate {
int x = 0;
int y = 0;
int cnt = 0;
Coordinate(int x, int y, int cnt) {
this.x = x;
this.y = y;
this.cnt = cnt;
}
}
총평: 최단거리 알고리즘은 BFS를 이용하면 쉽게 해결할 수 있다!
'플밍 > 문제풀이' 카테고리의 다른 글
[Java] BOJ1181, 백준 - 단어 정렬 (0) | 2021.09.04 |
---|---|
[Java] BOJ7576, 백준 - 토마토 (0) | 2021.09.03 |
[Java] BOJ4963, 백준 - 섬의 개수 (0) | 2021.09.03 |
[Java] BOJ1707, 백준 - 이분 그래프 (0) | 2021.09.03 |
[Java] BOJ13023, 백준 - ABCDE (0) | 2021.09.01 |