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

2025. 4. 24. 12:16·알고리즘

문제 출처

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

문제

N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로로 이동하려 한다. 최단경로는 맵에서 가장 적은 개수의 칸을 지나는 경로를 말하는데, 이때 시작하는 칸과 끝나는 칸도 포함해서 센다.

만약에 이동하는 도중에 한 개의 벽을 부수고 이동하는 것이 좀 더 경로가 짧아진다면, 벽을 한 개 까지 부수고 이동하여도 된다.

한 칸에서 이동할 수 있는 칸은 상하좌우로 인접한 칸이다.

맵이 주어졌을 때, 최단 경로를 구해 내는 프로그램을 작성하시오.

입력

첫째 줄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 1,000)이 주어진다. 다음 N개의 줄에 M개의 숫자로 맵이 주어진다. (1, 1)과 (N, M)은 항상 0이라고 가정하자.

출력

첫째 줄에 최단 거리를 출력한다. 불가능할 때는 -1을 출력한다.

예제 입력 1 복사

6 4
0100
1110
1000
0000
0111
0000

예제 출력 1 복사

15

예제 입력 2 복사

4 4
0111
1111
1111
1110

예제 출력 2 복사

-1

풀이 방법

  • 처음엔 그냥 BFS로 순환하면 되는 문제인줄 알았는데,, 벽이 반드시 시작점 주변에 있지 않다는 점과 한 번 부수면 다시는 부술 수 없는 점을 간과하고 풀어서 1차 실패
  • 다음엔 countMap을 이용해서 최소 이동경로를 저장한 다음 벽을 1회만 부수도록 boolean 변수 bomb를 설정하여 체크했으나 이 countMap만으로는 방문처리가 되지 않아 2차 실패
  • 그래서 그냥 visited를 3차원으로 선언하고, 벽을 안 부순 경우에서의 최소, 벽을 부순 경우에서의 최소를 각각 저장했다.
    • 어짜피, 최종 N , M 좌표에는 가장 최단거리인 놈이 먼저 도착할 것

풀이 코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
import java.util.StringTokenizer;

public class Main {
    static int N, M;
    static int[][] map;
    static boolean[][][] visited;
    static int[] dr = { -1, 1, 0, 0 };
    static int[] dc = { 0, 0, -1, 1 };

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        StringTokenizer st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());

        map = new int[N][M];
        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';
            }
        }
        int result = bfs();
        System.out.println(result);
    }

    public static int bfs() {
        Deque<Info> dq = new ArrayDeque<>();
        dq.add(new Info(0, 0, 1, false));
        visited[0][0][0] = true;

        while (!dq.isEmpty()) {
            Info cur = dq.poll();
            // 끝 점 도달 시
            if (cur.r == N - 1 && cur.c == M - 1) {
                return cur.count;
            }
            for (int d = 0; d < 4; d++) {
                int nr = cur.r + dr[d];
                int nc = cur.c + dc[d];
                //벽 부수는 기능 썼는지 확인
                int bombIdx = cur.bomb ? 1 : 0;

                if (checkArea(nr, nc)) {
                    if(map[nr][nc] == 0 && !visited[nr][nc][bombIdx]){
                        visited[nr][nc][bombIdx] = true;
                        dq.add(new Info(nr, nc, cur.count + 1, cur.bomb));
                    }
                    else if(map[nr][nc] == 1 && !cur.bomb && !visited[nr][nc][1]){
                        visited[nr][nc][1] = true;
                        dq.add(new Info(nr, nc, cur.count + 1, true));
                    }
                }
            }
        }

        return -1;
    }

    public static boolean checkArea(int r, int c) {
        if (r >= 0 && r < N && c >= 0 && c < M) {
            return true;
        }
        return false;
    }

    public static class Info {
        int r;
        int c;
        int count;
        boolean bomb;

        public Info(int r, int c, int count, boolean bomb) {
            this.r = r;
            this.c = c;
            this.count = count;
            this.bomb = bomb;
        }
    }
}

결과

회고

  • bfs가 재밌긴한데 머리가 제일 아픈 느낌이다.
저작자표시 비영리 동일조건 (새창열림)

'알고리즘' 카테고리의 다른 글

[백준] 치킨 배달 - Java  (1) 2025.04.30
[백준] Contact - Java  (0) 2025.04.29
[백준] 불 - Java  (0) 2025.04.23
[백준] 곱셈 - Java  (1) 2025.04.22
[백준] 하노이 탑 이동 순서 - Java  (1) 2025.04.21
'알고리즘' 카테고리의 다른 글
  • [백준] 치킨 배달 - Java
  • [백준] Contact - Java
  • [백준] 불 - Java
  • [백준] 곱셈 - Java
BGK97
BGK97
사용자 입장에서 한번 더 생각하는 개발자로 성장하고 싶은 사람입니다.
  • BGK97
    꾸준히, 열심히
    BGK97
  • 전체
    오늘
    어제
    • 분류 전체보기 (110)
      • 알고리즘 (73)
      • 컴퓨터 구조와 운영 체제 (8)
      • 네트워크 (5)
      • React (10)
      • 경험한 에러들 (3)
      • HTML, CSS, JavaScript (8)
      • 자료구조 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
BGK97
[백준] 벽 부수고 이동하기 - Java
상단으로

티스토리툴바