ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • BOJ) 벽 부수고 이동하기
    알고리즘/백준 2020. 7. 23. 15:51
    반응형

    벽 부수고 이동하기

     

    2206번: 벽 부수고 이동하기

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

    www.acmicpc.net

    풀이

     

    BFS 문제로, (1,1)에서 시작해서 (n,m)에 최소 경로로 도달하기 위해 몇 개의 칸을 밟는지 구하는 문제다.

    처음에는 단순하게 visit을 좌표만 체크하면서 (2차원 배열) 답을 구해줬다.

    50퍼센트 쯤 넘어갈 때 틀렸다고 뜨는 것을 보고, 벽을 허물고 이동한 경우와 벽을 허물지 않고 이동한 경우가 물린다는 것을 알아챘다.

     

    그래서 visit 변수를 3차원 배열로 생성해주었는데, 벽을 한 번 허물었을 경우 이동 기록과 허물지 않고 이동한 이동 기록을 나눠주기 위해서였다.   boolean[][][] visit = new boolean [n][m][2];

     

    처음 시작 위치를 넣을 때, step에 1, remain에 1을 넣어주었다.

    처음 시작하는 칸도 총 밟게되는 칸에 포함되기 때문에 step 은 1이 된다.

    처음 시작할 때는 벽을 허물지 않았으므로 remain은 1이 된다. ( 만약 벽을 세번 네번 허물 수있다면 remain은 그에따라 변한다. visit도)

     

    나머지는 일반적으로 BFS를 통해 맵을 탐색하는 것과 같다.

     

     

    코드

     

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.LinkedList;
    import java.util.StringTokenizer;
    
    public class Main {
        private final static char MOVE = '0', WALL = '1';
        private final static int[] dx = {1,-1,0,0}, dy = {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());
    
            int n = Integer.parseInt(st.nextToken());
            int m = Integer.parseInt(st.nextToken());
    
            char[][] map = new char[n][m];
            for(int i=0; i<n; i++) {
                map[i] = br.readLine().toCharArray();
            }
            br.close();
    
            solution(n,m,map);
        }
    
        private static void solution(int n, int m, char[][] map) {
            int answer =-1;
            LinkedList<Pos> moveList = new LinkedList<>();
            boolean[][][] visit = new boolean[n][m][2]; // 벽을 한 번 부순 경우와 부수지 않은 경우
            visit[0][0][1] = true; // 부수지 않은 채 이동
            moveList.offer(new Pos(0,0, 1,NO_BREAK));
    
            while(!moveList.isEmpty()) {
                Pos pos = moveList.poll();
                if(pos.x == m-1 && pos.y == n-1) {
                    answer = pos.step;
                    break;
                }
                int step = pos.step+1;
                int remain = pos.remain;
    
                for(int i=0; i<4; i++) {
                    int nx = pos.x + dx[i];
                    int ny = pos.y + dy[i];
                    if(isInArea(nx,ny,m,n)) { // out of idx 방지
                        if(!visit[ny][nx][remain]) { // visit check
                            if (map[ny][nx] == MOVE) {
                                moveList.offer(new Pos(nx,ny,step, remain));
                                visit[ny][nx][remain] = true;
                            } else { // 벽의 경우
                                if (remain == NO_BREAK) { // 벽을 한번도 안부쉈다면
                                    moveList.offer(new Pos(nx,ny,step, BREAK));
                                    visit[ny][nx][BREAK] = true;
                                }
                            }
    
                        }
                    }
                }
            }
            System.out.println(answer);
        }
    
        private static boolean isInArea(int x, int y, int m, int n) {
            return x>=0 && y>=0 && x<m && y<n;
        }
    
        private static class Pos {
            int x,y,step,remain;
            public Pos(int x, int y, int step, int remain) {
                this.x =x;
                this.y =y;
                this.step = step;
                this.remain =remain;
            }
        }
    }
    반응형

    '알고리즘 > 백준' 카테고리의 다른 글

    BOJ) 로봇 청소기  (0) 2020.07.24
    BOJ) 사탕 게임  (0) 2020.07.24
    BOJ) LCS  (0) 2020.07.23
    BOJ) 제곱수의 합  (0) 2020.07.22
    BOJ) 기타줄  (0) 2020.07.22

    댓글

Designed by Tistory.