📜 코딩테스트/BAEKJOON\BFS, DFS

백준 2206번 : 벽 부수고 이동하기 (JAVA) 문제 풀이

2021. 7. 7. 17:24
목차
  1. ✏️ 문제
  2. 🔐 문제 해결
  3. 🖥 전체 코드
반응형

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

 

2206번: 벽 부수고 이동하기

N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로

www.acmicpc.net


 

✏️ 문제

 

🔐 문제 해결

예를들어 아래와 같은 5X5 배열이 있다고 해보자

0 0 0 0 0
1 1 1 0 1
0 0 0 0 1
0 1 1 1 1
0 0 0 1 0

 

그림으로 표시하면 아래와 같을 것이다.

화살표 방향과 같이 시작점(0,0) 에서는 두 가지 방향으로 갈 수 있을 것이다.

하지만 1번으로 벽을 뚫고 간다면, 아래의 문제점에 부딪히게 된다.

도착지점으로 가기 위해서는 벽(빨간 지점)을 부숴야 하는데, 이미 벽을 부쉈으므로 가지 못하게 되어 1번 방향은 정답이 아니게 된다. 

그럼 2번 방향으로 진행을 한다면? 가는 길에 벽이 없기 때문에 빨간 지점까지는 도달할 수 있지만, 이미 1번 케이스에서 지나간 길을 방문 표시했기 때문에 도달하지 못하게 된다.

 

그렇기 때문에, 벽을 부수고 진행하는 케이스와 부수지 않고 진행하는 케이스의 방문 처리하는 배열을 하나로 두고 쓰면 이러한 문제점이 발생한다.

 

방문 처리 배열을 아래와 같이 선언해줘야 한다.

// 3차원 배열 : [벽을 부쉈는지 0,1]
boolean[][][] visit = new boolean[2][N][M];

 

다음 칸으로 이동할 때의 벽이 있는지 없는지에 따라서 처리하는 과정이 다음과 같다.

  • 다음 칸에 벽이 있을 경우
    1. 벽을 부순적이 없는지 체크
    2. 해당 벽을 이전에 부수고 방문한 적이 없는지
  • 다음 칸에 벽이 없을 경우
    1. 벽을 부순 여부에 따라 다음 칸을 방문했는지 체크

정확하게 이해가 되지 않는다면 아래의 코드를 참고하면 된다.

// 다음 칸에 벽이 있을 때 -> (1) 벽을 부순적이 없는지 체크
//                        (2) 이전의 '해당 벽'을 부수고 방문한적이 없는지 체크
if (miro[nX][nY] == '1') {
    if(cur[2] == 0 && !visit[1][nX][nY]){
        visit[cur[2]][nX][nY] = true;    // 방문 처리
        dist[nX][nY] = dist[cur[0]][cur[1]] + 1; // 거리 측정
        qu.offer(new int[]{nX, nY, 1});    // 다시 큐에 넣어줘서 BFS!
    }
}


// 벽이 아닐 경우 -> 벽을 "부순 여부"에 따른 방문을 했는지 체크!
else{
    if(!visit[cur[2]][nX][nY]){
        
        // 해당 칸을 방문을 안했을 때!
        visit[cur[2]][nX][nY] = true;    // 방문 처리
        dist[nX][nY] = dist[cur[0]][cur[1]] + 1; // 거리 측정
        qu.offer(new int[]{nX, nY, cur[2]}); // 다시 큐에 넣어줘서 BFS!
    }
}

// 도착지점에 도달 했을 때 출력하고 종료!
if(nX == N-1 && nY == M-1){
    System.out.print(dist[nX][nY] + 1);
    System.exit(0);
}

 

 

🖥 전체 코드

import java.util.*;
import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(bf.readLine());
        
        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());

        // 시작지점과 도착지점이 같을 경우!
        if(N-1 == 0 && M-1 == 0){
            System.out.print(1);
            System.exit(0);
        }
        
        int[] dx = {1, 0, -1, 0};
        int[] dy = {0, 1, 0, -1};

        char[][] miro = new char[N][M];  // 미로 배열
        int[][] dist = new int[N][M];    // 거리 측정 배열
        boolean[][][] visit = new boolean[2][N][M];    // 벽을 부순 여부에 따라 방문 여부 기록
        Queue<int[]> qu = new LinkedList<>();

        for (int i = 0; i < N; i++) {
            String s = bf.readLine();
            for (int j = 0; j < M; j++) {
                miro[i][j] = s.charAt(j);
            }
        }

        // 시작점 세팅 (x좌표, y좌표, crash 여부)
        qu.offer(new int[]{0, 0, 0});   

        while (!qu.isEmpty()) {
            int[] cur = qu.poll();  // 현재 위치 뽑기
            
            // 상,하,좌,우 탐색
            for(int i=0; i<4; i++){
                int nX = cur[0] + dx[i];
                int nY = cur[1] + dy[i];

                if (nX < 0 || nX >= N || nY < 0 || nY >= M) {
                    continue;
                }
                
                // 다음 칸에 벽이 있을 때 -> (1) 벽을 부순적이 있는지 체크
                //                        (2) 그 벽을 방문한적이 있는지 체크
                if (miro[nX][nY] == '1') {
                    if(cur[2] == 0 && !visit[1][nX][nY]){
                        visit[cur[2]][nX][nY] = true;    // 방문 처리
                        dist[nX][nY] = dist[cur[0]][cur[1]] + 1; // 거리 측정
                        qu.offer(new int[]{nX, nY, 1});    // 다시 큐에 넣어줘서 BFS!
                    }
                }
                // 벽이 아닐 경우 -> 벽을 "부순 여부"에 따른 방문을 했는지 체크!
                else{
                    if(!visit[cur[2]][nX][nY]){
                        // 해당 칸을 방문을 안했을 때!
                        visit[cur[2]][nX][nY] = true;    // 방문 처리
                        dist[nX][nY] = dist[cur[0]][cur[1]] + 1; // 거리 측정
                        qu.offer(new int[]{nX, nY, cur[2]}); // 다시 큐에 넣어줘서 BFS!
                    }
                }
                // 도착지점에 도달 했을 때 출력하고 종료!
                if(nX == N-1 && nY == M-1){
                    System.out.print(dist[nX][nY] + 1);
                    System.exit(0);
                }
            }
        }
        // 도달을 못했으므로 -1 출력!
        System.out.print(-1);
    }
}
반응형
저작자표시 (새창열림)
  1. ✏️ 문제
  2. 🔐 문제 해결
  3. 🖥 전체 코드
'📜 코딩테스트/BAEKJOON\BFS, DFS' 카테고리의 다른 글
  • 백준 9466번 : 텀 프로젝트 (JAVA) 문제 풀이
  • 백준 7569번 : 토마토 (JAVA) 문제 풀이
  • 백준 7576번 : 토마토 (JAVA) 문제 풀이
  • 백준 2178번 : 미로 탐색 (JAVA) 문제 풀이
iseunghan
iseunghan
꾸준하게 열심히..
iseunghan꾸준하게 열심히..
iseunghan
iseunghan

공지사항

  • 어제보다 나은 오늘이 되기 위해 🔥
  • 분류 전체보기 (262)
    • 💐 Spring (14)
      • 개념 및 이해 (2)
      • Spring 핵심 기술 (24)
      • Spring REST API (8)
      • Spring MVC, DB 접근 기술 (7)
      • Spring Security (23)
      • Spring in Action (1)
    • 🌻 JAVA (84)
      • 자바 ORM 표준 JPA 프로그래밍 (20)
      • 알고리즘, 자료구조 (13)
      • 디자인 패턴 (7)
      • 정리정리정리 (43)
      • JUnit (1)
    • 🔖 Snippets (3)
      • Javascript (3)
    • ⚙️ Devops (22)
      • ⛏ Git (11)
      • 🐳 Docker (6)
      • 🐧 Linux (3)
      • 🌈 Jenkins (1)
      • 📬 Kafka (1)
    • 💬 ETC.. (4)
      • 💻 macOS (2)
    • 🌧️ ORM (2)
      • JPA (2)
    • 🐍 Python (3)
    • 📚 Databases (15)
      • 오라클로 배우는 데이터베이스 개론과 실습(2판) (3)
      • RealMySQL 8.0 (8)
    • 🔥 Computer Science (5)
      • 📡 네트워크 (5)
    • 🏷️ 협업 (1)
    • 📜 코딩테스트 (38)
      • BAEKJOON\수학 1, 수학 2 (8)
      • BAEKJOON\재귀 (5)
      • BAEKJOON\브루트 포스 (3)
      • BAEKJOON\정렬 (1)
      • BAEKJOON\백트래킹 (5)
      • BAEKJOON\BFS, DFS (6)
      • BAEKJOON\이분탐색 (1)
      • BAEKJOON\다이나믹 프로그래밍 (9)
      • BAEKJOON\그리디 알고리즘 (0)
    • ✨ ISEUNGHAN (1)

인기 글

최근 글

전체
오늘
어제
반응형
hELLO · Designed By 정상우.
iseunghan
백준 2206번 : 벽 부수고 이동하기 (JAVA) 문제 풀이
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.