반응형
https://www.acmicpc.net/problem/2206
2206번: 벽 부수고 이동하기
N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로
www.acmicpc.net

풀이
기본적인 bfs 에 간단한 조건만 추가하면 해결 할 수 있는 문제이다.
시작점 (0, 0) 에서 도착점 (N, M) 으로 갈 수 있는 최단 거리를 구하면 된다.
Position 클래스를 생성할 때 x 좌표, y 좌표, 거리, 벽을 부셨는지 여부를 함께 저장할 수 있도록 선언한다.
public static class Position { int x; // x 좌표 int y; // y 좌표 int cnt; // 거리 int isBroken; // 벽을 부셨는지 여부 public Position (int x, int y, int cnt, int isBroken) { this.x = x; this.y = y; this.cnt = cnt; this.isBroken = isBroken; } }
상하좌우 한 칸씩 이동할 때 다음 칸이 벽일 경우, 벽이 아닐 경우 두 가지로 나누어서 조건을 만들면 된다.
1. 다음 칸이 벽일 경우
1) 벽을 부셨는지 여부 판단 (now.isBroken)
2) 해당 벽을 이전에 부수고 방문한 적이 있는지 판단 (visited[dx][dy][1])
2. 다음 칸이 벽이 아닐 경우
1) 벽을 부셨는지 여부에 따라 다음 칸을 방문했는지 판단 (visited[dx][dy][0] or visited[dx][dy][1])
// map 범위를 벗어나거나 벽을 이미 한 번 부셨을 경우 if (dx < 0 || dx >= N || dy < 0 || dy >= M || visited[dx][dy][now.isBroken]) continue; if (map[dx][dy] == 0) { // 다음 칸이 벽이 아닌 경우 visited[dx][dy][now.isBroken] = true; q.add(new Position(dx, dy, now.cnt+1, now.isBroken)); } else if (map[dx][dy] == 1 && now.isBroken == 0) { // 다음 칸이 벽이고 아직 벽을 부수지 않은 경우 visited[dx][dy][1] = true; q.add(new Position(dx, dy, now.cnt+1, 1)); }
위 과정을 판단하기 위해선 visited 배열을 3차원 배열로 생성해주면 된다.
visited[x][y][벽을 부셨는지 여부]
<최종코드>
import java.io.*; import java.util.*; public class Main { static int[] x = {-1, 0, 1, 0}; static int[] y = {0, -1, 0, 1}; public static class Position { int x; // x 좌표 int y; // y 좌표 int cnt; // 거리 int isBroken; // 벽을 부셨는지 여부 public Position (int x, int y, int cnt, int isBroken) { this.x = x; this.y = y; this.cnt = cnt; this.isBroken = isBroken; } } 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[][] map = new int[N][M]; boolean[][][] visited = new boolean[N][M][2]; for (int i=0; i<N; i++) { String str = br.readLine(); for (int j=0; j<M; j++) { map[i][j] = str.charAt(j) - '0'; } } Queue<Position> q = new LinkedList<>(); q.add(new Position(0, 0, 1, 0)); visited[0][0][0] = true; while (!q.isEmpty()) { Position now = q.poll(); // 먼저 도착지에 도달한 경우 dfs 종료 if (now.x == N-1 && now.y == M-1) { System.out.println(now.cnt); return; } for (int i=0; i<4; i++) { int dx = now.x + x[i]; int dy = now.y + y[i]; // map 범위를 벗어나거나 벽을 이미 한 번 부셨을 경우 if (dx < 0 || dx >= N || dy < 0 || dy >= M || visited[dx][dy][now.isBroken]) continue; if (map[dx][dy] == 0) { // 다음 칸이 벽이 아닌 경우 visited[dx][dy][now.isBroken] = true; q.add(new Position(dx, dy, now.cnt+1, now.isBroken)); } else if (map[dx][dy] == 1 && now.isBroken == 0) { // 다음 칸이 벽이고 아직 벽을 부수지 않은 경우 visited[dx][dy][1] = true; q.add(new Position(dx, dy, now.cnt+1, 1)); } } } // 도착지에 도달하지 못 할 경우 System.out.println(-1); } }
반응형
'알고리즘 > DFS & BFS' 카테고리의 다른 글
[백준]JAVA - 19238번: 스타트 택시 (0) | 2022.12.05 |
---|---|
[백준]JAVA - 1600번: 말이 되고픈 원숭이 (0) | 2022.11.26 |
[백준]JAVA - 1937번: 욕심쟁이 판다 (0) | 2022.11.07 |
[백준]JAVA - 16234번: 인구 이동 (0) | 2022.11.03 |
[백준]JAVA - 14502번: 연구소 (0) | 2022.10.25 |