백준 16954 - 움직이는 미로 탈출

Updated:

Java

16954 번 - 움직이는 미로 탈출

문제

접근 방법

BFS의 응용문제 토마토의 접근법과 비슷하게 해결하였다.

BFS의 while 내부에 또 다른 while을 두어 2중 반복을 수행하였는데
이는 queue의 좌표가 먼저 움직이고 벽이 아래로 이동하기 때문에 먼저 큐의 크기만큼 반복한다.

이후 제자리에 머무는 경우를 포함하여 8방향으로 앞으로 다음 턴에 벽이 내려오지 않는다면, 그 좌표를 add하며 BFS로 원하는 목표 위치에 도달하는지 판별한다.

코드

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

public class Main {
	static int n, m, result;
	static char[][] map;
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    	
    	n = 8;
    	
    	map = new char[n][n];
    	boolean[][] vis = new boolean[n][n];
    	
    	for(int i = 0; i < 8; i++)
    		map[i] = br.readLine().toCharArray();
    	
    	Queue<int[]> queue = new LinkedList<int[]>();
    	queue.add(new int[] {n - 1,0});
    	
    	int[] dy = {-1,-1,-1,0,0,1,1,1};
    	int[] dx = {-1,0,1,-1,1,-1,0,1};
    	
    	int[] q;
    	int y,x,ny,nx, chk_ny, count;
		// 한번 loop가 돌 때마다 벽이 내려온다.
    	quit : while(!queue.isEmpty()) {
    		count = queue.size();
    		vis = new boolean[n][n];
    		// 현재 이동할 좌표들의 개수만큼 반복
    		while(count-- != 0) {
    			q = queue.poll();
        		y = q[0];
        		x = q[1];
        		
        		// 바로 위에 돌이 없다면, 제자리에 한번 머문다.
        		ny = y - 1;  
        		nx = x;
        		if(isIn(ny,nx) && map[ny][x] != '#') {
        			queue.add(new int[] {y,x});
        		}
        		// 8방향 탐색
        		for(int i = 0; i < 8; i++) {
            		ny = y + dy[i];
            		nx = x + dx[i];
            		// 제일 위애 도달하면, 목표 위치까지 벽이 없으므로 도달 가능
            		if(ny == 0) {
            			result = 1;
            			break quit;
            		}
            		
            		chk_ny = ny - 1;
            		if(chk_ny < 0)
            			continue;
            		// 현재 위치에 이동할 수 있고, 이후 벽이 내려오지 않으면서 방문하지 않았으면
            		if(isIn(ny,nx) && map[chk_ny][nx] != '#' && !vis[ny][nx]) {
            			queue.add(new int[] {ny,nx});
            			vis[ny][nx] = true;
            		}
        		}
    		}
    		
			// 벽이 내려옴
    		for(int i = 7; i >= 1; i--) {
    			map[i] = map[i - 1].clone();
    		}
    		Arrays.fill(map[0], '.');
    	}
    	System.out.println(result);
    	br.close();
	}
	static boolean isIn(int y, int x) {
		if(0 <= y && y < n && 0 <= x && x < n && map[y][x] != '#')
			return true;
		return false;
	}
	static int stoi(String str) {
    	return Integer.parseInt(str);
    }
}

총평

후기

방문 배열을 사용하지 않아도 해결 가능하지만, 쓰는 것이 시간 단축의 도움을 확인하였다.

개선할 점