ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Algorithm] 백준 2206번 : 벽 부수고 이동하기
    카테고리 없음 2020. 9. 9. 23:25

     

    https://www.acmicpc.net/problem/2206

     

    2206번: 벽 부수고 이동하기

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

    www.acmicpc.net

     

     

    이 문제에서 어려웠던 부분은, 벽을 부수거나 안부술 수 있고, 그 기회는 오직 1번이라는 것!

     

    dfs는 재귀로 경우 나눠서 풀면되는데

     

    bfs에서 경우를 나누는 법이 도저히 생각이 안났다.

     

    그러다가 힌트를 봄.

     

    check(방문을 체크하는 배열)의 차원을 늘려서 

     

    마지막 차원을 부쉈는지 여부를 넣어주면(0: 안부숨, 1: 부숨)

     

    2가지의 방문 경우의 수가 생기고

     

    벽을 마주칠 때 아직 부순 경험이 없다면

     

    부수고 check의 마지막 차원이 1인 곳에 방문 표시를 해주고, 큐에 넣어주면 된다.

     

     

    ** 주의할 것 -> bfs 풀때 뭔가에 도달했을때 return하는거면 pop할때 조건확인하고 리턴하는걸로 하자 (이것때문에 몇시간을 날림)

     

     

     

     

    Code

    #include <iostream>
    #include <string>
    #include <vector>
    #include <queue>
    
    using namespace std;
    
    struct pos
    {
        int x, y, dist, destroy;
    };
    
    int main() {
        int n, m;
        queue<pos> q;
        int check[1000][1000][2] = {0, }, v[1000][1000] = {0, };
        int mv[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    
        cin >> n >> m;
    
        for(int i=0; i<n; i++) {
            string tmp;
            cin >> tmp;
            for(int j=0; j<m; j++) {
                v[i][j] = tmp[j] - '0';
            }
        }
    
        check[0][0][0] = 1; 
        q.push({0, 0, 1, 0});
    
        while(!q.empty()){
            int x = q.front().x;
            int y = q.front().y;
            int dist = q.front().dist;
            int destroy = q.front().destroy;
    
            q.pop();
    
            // 도착했으면 리턴
            if(x == n-1 && y == m-1) {
                cout << dist;
                return 0;
            }
            
            for(int i=0; i<4; i++) {
                int nx = x + mv[i][0];
                int ny = y + mv[i][1];
                int ndist = dist + 1;
                
                int ndestroy = destroy;
                
                if (nx>=0 && ny>=0 && nx<n && ny<m && check[nx][ny][ndestroy]==0) {
                    if(v[nx][ny]==1 && ndestroy==0) {
                        ndestroy = 1;
                        check[nx][ny][ndestroy] = 1;
                        q.push({nx, ny, ndist, ndestroy});
                    }
                    else if(v[nx][ny]==0) {
                        check[nx][ny][ndestroy] = 1;
                        q.push({nx, ny, ndist, ndestroy});
                    }
                    
                }
            }     
        }
    
        cout << -1;
        return 0;
    }

    댓글

dokylee's Tech Blog