본문 바로가기
백준

[JAVA] 백준 2206 - 벽 부수고 이동하기

by 맴썰 2025. 9. 4.

https://www.acmicpc.net/problem/2206

전형적인 BFS문제처럼 보이지만 벽을 하나 부술 수 있는 문제라서 상당히 복잡했다.

핵심 개념을 떠올리기가 힘들어서 일단 바이러스 문제처럼 브루트포스식으로 해봤는데 시간이 어림도 없었다.

결국 핵심 개념은 특정 좌표 (X,Y)까지 도착했을 때 벽을 부쉈는지 안 부쉈는지의 상태를 저장할 수 있어야하고, 그에 따라 경로도 완전히 달라지기 때문에 별도로 관리되어야 한다는 점이다.

그래서 방문체크배열을 3차원으로 추가해 [x][y][벽부쉈는지] 형식으로 작성하고 BFS를 돌리다가 벽을 만나면 부수고 부순쪽의 방문체크를 하고 길을 만난 경우에는 부수지 않는 쪽의 방문체크를 하면서 목적지인 (N,M)에 도달해서 최단경로가 산출됐는지를 체크했다.

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int[] a = Arrays.stream(br.readLine().split(" ")).mapToInt(Integer::parseInt).toArray();
        int h = a[0];
        int w = a[1];
        int[][] map = new int[h][w];
        for (int i = 0; i < h; i++) {
            String s = br.readLine();
            for (int j = 0; j < s.length(); j++) {
                map[i][j] = Character.getNumericValue(s.charAt(j));
            }
        }
        int[] dx = {1, -1, 0,0};
        int[] dy = {0,0,1,-1};
        boolean[][][] visited = new boolean[map.length][map[0].length][2];
        Queue<Position> q = new LinkedList<>();
        q.offer(new Position(0, 0, 1,0));
        visited[0][0][0] = true;
        int len = Integer.MAX_VALUE;
        while (!q.isEmpty()) {
            Position cur = q.poll();
            int ch = cur.h;
            int cw = cur.w;
            int depth = cur.depth;
            int cbr = cur.br;
            if (ch == map.length - 1 && cw == map[0].length - 1) {
                len = Math.min(len, depth);
            }
            for (int i = 0; i < 4; i++) {
                int ti = ch+dx[i];
                int tj = cw+dy[i];
                if(ti<0||ti>=map.length||tj<0||tj>=map[0].length) continue;
                if(map[ti][tj]==0&&!visited[ti][tj][cbr]){
                    visited[ti][tj][cbr] = true;
                    q.offer(new Position(ti,tj,depth+1,cbr));
                }
                if(map[ti][tj]==1&&cbr==0&&!visited[ti][tj][1]){
                    visited[ti][tj][1] = true;
                    q.offer(new Position(ti,tj,depth+1,1));
                }
            }
        }

        if(len==Integer.MAX_VALUE) System.out.println(-1);
        else System.out.println(len);
    }


}

class Position {
    int h;
    int w;
    int depth;
    int br;

    Position(int h, int w, int d, int br) {
        this.h = h;
        this.w = w;
        this.depth = d;
        this.br = br;
    }
}

맨날 상하좌우 체크할때 파라미터 일일히 쓰기 힘들었는데

       int[] dx = {1, -1, 0, 0};
       int[] dy = {0, 0, 1, -1};

이렇게 쓰는 습관을 들이면 속도가 좀더 빨라질 것 같다.

'백준' 카테고리의 다른 글

[JAVA] 백준 2638 - 치즈  (0) 2025.09.06
[JAVA] 백준 5052 - 전화번호 목록  (0) 2025.09.05
[JAVA] 백준 1865 - 웜홀  (0) 2025.09.03
[JAVA] 백준 1238 - 파티  (0) 2025.09.02
[JAVA] 백준 30805 - 사전 순 최대 공통 부분 수열  (0) 2025.09.02