Algorithm/코딩테스트

[코딩테스트] 백준 - BFS 미로 탐색

jjuya 개발 기록 2024. 5. 9. 00:01

백준 2178번 미로탐색 

시간제한 메모리 제한
1 초 192 MB

 

 

문제

N×M크기의 배열로 표현되는 미로가 있다.

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

미로에서 1은 이동할 수 있는 칸을 나타내고, 0은 이동할 수 없는 칸을 나타낸다. 이러한 미로가 주어졌을 때, (1, 1)에서 출발하여 (N, M)의 위치로 이동할 때 지나야 하는 최소의 칸 수를 구하는 프로그램을 작성하시오. 한 칸에서 다른 칸으로 이동할 때, 서로 인접한 칸으로만 이동할 수 있다.

위의 예에서는 15칸을 지나야 (N, M)의 위치로 이동할 수 있다. 칸을 셀 때에는 시작 위치와 도착 위치도 포함한다.

 

 

입력

첫째 줄에 두 정수 N, M(2 ≤ N, M ≤ 100)이 주어진다. 다음 N개의 줄에는 M개의 정수로 미로가 주어진다. 각각의 수들은 붙어서 입력으로 주어진다.

 

 

출력

첫째 줄에 지나야 하는 최소의 칸 수를 출력한다. 항상 도착위치로 이동할 수 있는 경우만 입력으로 주어진다.

 

 

💡슈도코드 작성

dx,dy (상하좌우를 탐색하기 위한 defne값 정의 변수)  // x가 행, y가 열 
A(데이터 저장 2차원 행렬)
N(row), M(column)
visited(방문 기록 저장 배열)
A 배열 초기화 하기
visited 배열 초기화 하기
------------------------------------------------------------- 
for(N의 개수만큼 반복하기){
    for(M의 개수만큼 반복하기){
       A 배열에 데이터 저장하기
    }
}
------------------------------------------------------------- 문제 데이터 받는 부분
BFS(0,0) 실행하기
BFS{  // BFS 구현하기
    큐 자료구조에 시작 노드 삽입하기(add연산)
    vusted 배열에 현재 노드 방문 기록하기
    while(큐가 비어있을 때까지){
        큐에서 노드 데이터를 가지고 오기(poll연산)
        for(상하좌우 탐색){
            if(유효한 좌표){
               if(이동할 수 있는 칸이면서 방문하지 않은 노드){
                   visited 배열에 방문 노드 기록하기
                   A 배열에 depth를 현재 노드를 depth+1로 업데이트하기
                   큐에 데이터 삽입하기 (add)

               }
            }
        }
    }

 

 

💡코드 작성

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class 미로탐색 {
    static int[] dx = {0,1,0,-1};
    static int[] dy = {1,0,-1,0};
    static boolean[][] visited;
    static int[][] A;
    static int N,M;
    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());
        A = new int[N][M];
        visited = new boolean[N][M];
        for(int i = 0;i<N;i++){
            st = new StringTokenizer(br.readLine());
            String lline = st.nextToken(); // 10111001
            for(int j = 0;j<M;j++){
                A[i][j] = Integer.parseInt(lline.substring(j,j+1));
            }
        }
        BFS(0,0);
        System.out.println(A[N-1][M-1]);
    }

    private static void BFS(int i, int j) {
        Queue<int[]> queue = new LinkedList<>();
        queue.offer(new int[]{i,j}); //시작점
        visited[i][j] = true;
        while (!queue.isEmpty()){ //큐가 빌때까지 탐색
            int now[] = queue.poll();            
            for(int k=0; k<4; k++){ //상하좌우 탐색
                int x = now[0] + dx[k];
                int y = now[1] + dy[k];
                if(x > 0 && y >0 && x < N && y < M){ //배열을 넘어가면 안되고
                    if(A[x][y] !=0&& !visited[x][y]){ //0이여서 갈 수 없거나 방문한곳이면안됨
                        // 이제 탐색 가능
                        visited[x][y] = true;
                        A[x][y] = A[now[0]][now[1]] + 1; //핵심
                        queue.add(new int[] {x,y});
                    }
                }
            }
        }
    }
}