알고리즘/L19 BFS,DFS

19. 목수의 미로 탈출

쿠쿠트레인 2023. 7. 19. 15:10

문제


아래와 같이 이동할 수 있는 길, 그리고 이동할 수 없는 벽으로 이루어진 크기 N x M 의 지도가 주어진다. 이 때, (N-1, 0) 에서 출발하여 (0, M-1) 까지 도착하는 최단거리를 찾으려 한다. 그런데 목수는 도끼 하나를 갖고 있으며, 이 도끼를 이용하여 벽을 깨부술 수 있다. 하지만 이 도끼는 내구성이 그렇게 좋지 않기 때문에, 벽을 최대 1개밖에 깰 수 없다. 목수가 출발점에서 도착점까지 이동하기 위한 최단거리를 출력하는 프로그램을 작성하시오. 물론, 벽은 최대 1개까지 깰 수 있다. 아래 예제의 경우 ‘X’ 로 표시된 벽을 깰 경우 거리 18만에 출발점에서 도착점으로 이동할 수 있다.

 

입력


첫째 줄에 지도의 세로 길이 N과 지도의 가로 길이 M이 주어진다. ( 1 ≤ N, M ≤ 1,000 ) 둘째 줄부터 지도의 정보가 주어진다. 0은 이동할 수 있는 부분, 1은 이동할 수 없는 부분을 나타낸다.

 

출력


목수가 (N-1, 0) 에서 출발하여 (0, M-1) 까지 이동하는 데 필요한 최단거리를 출력한다. 목수는 미로를 항상 탈출할 수 있다고 가정한다.

 

예제 입력

10 10
0 0 0 0 0 0 1 1 0 0
0 1 1 1 0 0 1 0 1 0
0 1 1 1 0 0 1 0 1 0
0 0 0 0 0 0 0 0 1 0
0 0 1 1 1 1 0 0 1 0
0 0 0 0 0 0 1 1 0 0
0 0 1 1 1 0 1 1 0 0
0 0 1 1 1 0 0 0 0 0
0 0 0 0 0 1 1 1 0 0
0 0 0 0 0 0 0 1 0 0

예제 출력

18

 

예제 입력

10 10
0 0 0 0 0 0 1 1 0 0
0 1 1 1 0 0 1 1 1 0
0 1 1 1 0 0 1 1 1 0
0 0 0 0 0 0 0 1 1 0
0 0 1 1 1 1 0 1 1 0
0 0 0 0 0 0 1 1 0 0
0 0 1 1 1 0 1 1 0 0
0 0 1 1 1 0 0 1 0 0
0 0 0 0 0 1 1 1 1 1
0 0 0 0 0 0 0 1 0 0

예제 출력

22
#include <iostream>
#include <queue>
#include <algorithm>

using namespace std;

const int MAX = 1005;

int arr[MAX][MAX];
int check[MAX][MAX];
int n,m;

int checkR[MAX][MAX];

typedef struct coor{
  int n;
  int m;
  coor(){};
  coor(int _n,int _m):n(_n),m(_m){};
}coor;
queue <coor> q;

int dx[4] = {0,-1,1,0};
int dy[4] = {1,0,0,-1};

bool inside(int a,int b){
  return (a>=0 && a<n) && (b>=0&&b<m);
}

int flag = 0;
int cnt = 0;

void BFS(){
  if(q.empty()&&flag!=0) return;
  coor now = q.front();
  q.pop();
  
  int a,b;
  a = now.n;
  b = now.m;
  
  int temp = check[a][b];
  
  int nx,ny;
  for(int i=0;i<4;i++){
    nx = a+dx[i];
    ny = b+dy[i];
    if(inside(nx,ny)&&check[nx][ny]==0&&arr[nx][ny]!=1){
      now.n = nx;
      now.m = ny;
      q.push(now);
      check[nx][ny] = temp+1;
    }
  }
  if(!q.empty() && flag==0) BFS();
}

void BFS_R(){
  if(q.empty()&&flag!=0) return;
  coor now = q.front();
  q.pop();
  
  int a,b;
  a = now.n;
  b = now.m;
  
  int temp = checkR[a][b];
  
  int nx,ny;
  for(int i=0;i<4;i++){
    nx = a+dx[i];
    ny = b+dy[i];
    if(inside(nx,ny)&&checkR[nx][ny]==0&&arr[nx][ny]!=1){
      now.n = nx;
      now.m = ny;
      q.push(now);
      checkR[nx][ny] = temp+1;
    }
  }
  if(!q.empty() && flag==0) BFS_R();
}

int main(){
  
  scanf("%d %d",&n,&m);
  
  for(int i=0;i<n;i++){
    for(int j=0;j<m;j++){
      scanf("%d",&arr[i][j]);
    }
  }
  
  check[n-1][0] = 1;
  q.push(coor(n-1,0));
  BFS();
  
  checkR[0][m-1] = 1;
  q.push(coor(0,m-1));
  BFS_R();
  
  int min = 987987987;
  for(int i=0;i<n;i++){
    for(int j=0;j<m;j++){
      
      int sm=987987987,em=987987987;
      
      if(arr[i][j]==1){
        int nx, ny;
        
        for(int q=0;q<4;q++){
          nx = i+dx[q];
          ny = j+dy[q];
          
          if(inside(nx,ny)){
            if(sm>check[nx][ny] && check[nx][ny]!=0) sm = check[nx][ny];
            if(em>checkR[nx][ny] && checkR[nx][ny]!=0) em = checkR[nx][ny];
            if(min>sm+em) min = sm+em;
          }
        }
      }
    }
  }
  
  printf("%d",min);
  return 0;
}

https://github.com/kuminkyu/SoloStudy/blob/master/AlgorithmTest/level19/%EB%AA%A9%EC%88%98%EC%9D%98%20%EB%AF%B8%EB%A1%9C%20%ED%83%88%EC%B6%9C.c%2B%2B