DFS, BFS 활용 - 0811. 미로의 최단거리 통로(BFS)
private static final int SIZE = 7;
private static int[][] maze = new int[SIZE][SIZE];
private static class Position {
int x, y;
public Position(int x, int y) {
this.x = x;
this.y = y;
}
public boolean moveDown() {
if(x+1 < SIZE && maze[x+1][y] == 0) {
maze[x+1][y] = 1;
return true;
}
return false;
}
public boolean moveUp() {
if(x-1 >= 0 && maze[x-1][y] == 0) {
maze[x-1][y-1] = 1;
return true;
}
return false;
}
public boolean moveRight() {
if(y+1 < SIZE && maze[x][y+1] == 0) {
maze[x][y+1] = 1;
return true;
}
return false;
}
public boolean moveLeft() {
if(y-1 >= 0 && maze[x][y-1] == 0) {
maze[x][y-1] = 1;
return true;
}
return false;
}
}
private static int BFS(int x, int y) {
int answer = 0;
Queue<Position> Q = new LinkedList<>();
Q.add(new Position(0, 0));
maze[0][0] = 1;
while(!Q.isEmpty()) {
int len = Q.size();
for(int i=0; i<len; i++) {
Position p = Q.poll();
if(p.x==SIZE-1 && p.y==SIZE-1) return answer;
if(p.moveDown()) Q.add(new Position(p.x+1, p.y));
if(p.moveRight()) Q.add(new Position(p.x, p.y+1));
if(p.moveUp()) Q.add(new Position(p.x-1, p.y));
if(p.moveLeft()) Q.add(new Position(p.x, p.y-1));
}
answer++;
}
return -1;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
for(int i=0; i<maze.length; i++) {
for(int j=0; j<maze.length; j++) {
maze[i][j] = sc.nextInt();
}
}
System.out.println(BFS(0, 0));
}
class Point{
public int x, y;
Point(int x, int y){
this.x=x;
this.y=y;
}
}
class Main {
static int[] dx={-1, 0, 1, 0};
static int[] dy={0, 1, 0, -1};
static int[][] board, dis;
public void BFS(int x, int y){
Queue<Point> Q=new LinkedList<>();
Q.offer(new Point(x, y));
board[x][y]=1;
while(!Q.isEmpty()){
Point tmp=Q.poll();
for(int i=0; i<4; i++){
int nx=tmp.x+dx[i];
int ny=tmp.y+dy[i];
if(nx>=1 && nx<=7 && ny>=1 && ny<=7 && board[nx][ny]==0){
board[nx][ny]=1;
Q.offer(new Point(nx, ny));
dis[nx][ny]=dis[tmp.x][tmp.y]+1;
}
}
}
}
public static void main(String[] args){
Main T = new Main();
Scanner kb = new Scanner(System.in);
board=new int[8][8];
dis=new int[8][8];
for(int i=1; i<=7; i++){
for(int j=1; j<=7; j++){
board[i][j]=kb.nextInt();
}
}
T.BFS(1, 1);
if(dis[7][7]==0) System.out.println(-1);
else System.out.println(dis[7][7]);
}
}
해당 문제는 BFS
를 이용하여 풀 수 있다. 나의 풀이에서는 Position
이라는 클래스를
생성하여 현재 위치를 보관하고, 상하좌우 움직임이 가능한지를 체크할 수 있는 메소드를
두었다. 또한 동시에 해당 칸의 방문을 같이 체크하도록 하였다.
이후 시작 위치를 Queue
에 보관 후, BFS
를 수행하며 현재 Queue
에 보관된 칸들에서
갈 수 있는 상하좌우의 칸들을 Queue
에 다시 집어넣으며 탐색하는 로직이다.
목표 지점에 도착할 시 Queue
를 몇 번 순회했는지(이동 횟수) 반환하여 문제를 해결한다.
강의에서는 이전 미로 탐색문제와 동일하게 dx
와 dy
배열을 두고 반목문을 수행하여
상하좌우 탐방을 수행한다. 미로를 벗어나는 경우나 이미 방문한 칸을 체크하는 조건문을
확인하여 BFS
를 수행하고 문제를 해결한다.
어.. 강의 코드에서 최단 거리를 구할 수 있는거 맞아?
처음 강의를 보았을 때 아래와 같은 의문이 들었다.
최단 거리라면 처음 목적지에 도착했을 때 탐색을 멈추고 무언가 반환해야지.
이후 탐색에서 다른 값이 들어가면 어쩌려고?
는 생각도 잠시 천천히 다시 살펴보니 이미 방문한 위치는 재방문을 하지 않는다는
사실을 떠올리며, 최초로 목적지 도달 후 이후 탐색에서는 목적지 칸을 방문할 수
없다는 사실을 깨달았다고한다...😊