[백준 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
댓글을 사용할 수 없습니다.