[백준 2206 : JAVA] 벽 부수고 이동하기 / BFS
문제
풀이
2차원 평면이 주어질 때, 출발지에서 목적지까지의 단순 거리를 BFS 탐색을 통해 알아내는 문제다.
가장 기본적인 BFS 문제 유형에서 1개의 벽을 부술 수 있다는 한 가지 조건이 추가된 문제다.
추가된 위 조건으로 인해 생긴 고려사항은 다음과 같다.
- 기존에 (x, y) 좌표와 거리 값을 담는 distance 변수 외에 해당 좌표로 오기까지 벽을 부순 횟수를 저장할 변수가 하나 더 필요하다.
- 탐색할 다음 좌표가 벽이더라도 지금까지 벽을 부순 횟수가 0이라면 벽을 부수고 지날 수 있다.
- 기존에는 visited 변수를 통해 해당 좌표를 방문했는지만 체크했지만, 여기선 추가로 방문 여부 + 벽을 부순 횟수를 체크해야한다.
따라서, visited 변수를 boolean 타입이 아닌 int 타입으로 선언함.
위의 세 번째 조건을 보자. 방문했는지의 여부와 벽을 부순 횟수를 추가로 저장해야하는데 다음 그림을 보자.
BFS로 탐색하면 길을 탐색할텐데, 하나는 벽을 부수고 왔고, 하나는 안 부수고 왔다. 이때는 안 부수고 온 쪽을 기준으로 한다.
벽을 한 번도 안 부수고온 쪽이 먼저 탐색했다면, visited[ny][nx]에는 0이 담기므로 벽을 부수고온 쪽에서는 탐색할 필요가 없다.
벽을 한 번 부수고온 쪽이 먼저 탐색한다면, visited[ny][nx]에는 1이 담기므로 벽을 안 부수고온 쪽에서 새로 탐색한다.
if (visited[ny][nx] > point.drill) {
....
}
코드
import java.io.*;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
public class Main {
private static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
private static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
private static int N, M;
private static int[][] map;
private static int[][] visited;
private static int[] dx = {0, 0, -1, 1};
private static int[] dy = {-1, 1, 0, 0};
static class Point {
int x, y, distance;
int drill; // 공사 횟수
public Point(int x, int y, int distance, int drill) {
this.x = x;
this.y = y;
this.distance = distance;
this.drill = drill;
}
}
public static void main(String[] args) throws IOException {
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
map = new int[N][M];
visited = new int[N][M];
for (int i = 0; i < N; i++) {
String str = br.readLine();
for (int j = 0; j < M; j++) {
map[i][j] = Integer.parseInt(String.valueOf(str.charAt(j)));
visited[i][j] = Integer.MAX_VALUE;
}
}
int ans = bfs(0, 0);
bw.write(ans + "\n");
bw.flush();
bw.close();
br.close();
}
private static int bfs(int x, int y) {
Queue<Point> q = new LinkedList<>();
q.add(new Point(x, y, 1, 0)); // (1, 1)에서 시작
visited[y][x] = 0; // 처음 공사 횟수
while (!q.isEmpty()) {
Point point = q.poll();
// 도착지점을 만났다면 종료한다.
if (point.x == M - 1 && point.y == N - 1)
return point.distance;
for (int i = 0; i < 4; i++) {
int nx = point.x + dx[i];
int ny = point.y + dy[i];
if (nx >= 0 && nx < M && ny >= 0 && ny < N) {
if (visited[ny][nx] > point.drill) {
if (map[ny][nx] == 0) { // 벽이 아닐 때
q.add(new Point(nx, ny, point.distance + 1, point.drill));
visited[ny][nx] = point.drill;
} else { // 벽일 때
if (point.drill == 0) { // 지금까지 벽을 부순 횟수가 0이라면
q.add(new Point(nx, ny, point.distance + 1, point.drill + 1));
visited[ny][nx] = point.drill + 1;
}
}
}
}
}
}
return -1;
}
}
'Algorithm > Baekjoon' 카테고리의 다른 글
[백준 11438 : JAVA] LCA 2 / 최소 공통 조상 (0) | 2020.09.11 |
---|---|
[백준 13418 : JAVA] 학교 탐방하기 / MST (0) | 2020.09.09 |
[백준 9370 : JAVA] 미확인 도착지 / 다익스트라 (0) | 2020.08.28 |
[백준 11057 : C++] 오르막 수 / DP (0) | 2019.10.24 |
[백준 11559 : C++] Puyo Puyo / BFS, DFS (0) | 2019.10.18 |
댓글
이 글 공유하기
다른 글
-
[백준 11438 : JAVA] LCA 2 / 최소 공통 조상
[백준 11438 : JAVA] LCA 2 / 최소 공통 조상
2020.09.11 -
[백준 13418 : JAVA] 학교 탐방하기 / MST
[백준 13418 : JAVA] 학교 탐방하기 / MST
2020.09.09 -
[백준 9370 : JAVA] 미확인 도착지 / 다익스트라
[백준 9370 : JAVA] 미확인 도착지 / 다익스트라
2020.08.28 -
[백준 11057 : C++] 오르막 수 / DP
[백준 11057 : C++] 오르막 수 / DP
2019.10.24