ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백준 2206 (벽 부수고 이동하기) c++
    백준 문제 2022. 2. 25. 15:39
    728x90

    문제

     

    2206번: 벽 부수고 이동하기

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

    www.acmicpc.net

    행렬의 크기 nm이 주어지면 1이면 벽이고 0이면 갈 수 있는 길입니다.

    이때 벽을 한번 부수고 통과할 수 있다고 할때 최단거리를 구하는 문제입니다.

     

    최단 거리이므로 BFS로 이용하면 됩니다.

     

    원래 평소대로라면 bool visited[x][y] : arr[x][y]에 해당하는 부분을 방문하면 true로 바꿔주었지만

    벽을 부수는 경우도 생각해줘야 하기때문에 방문기록이 총 3차원으로 생각할 수 있습니다.

    int dist[x][y][0] : 벽을 하나도 안부수고 arr[x][y]까지 도달할 동안 최단거리

    int dist[x][y][1] : 벽을 한번 부수고 arr[x][y]까지 도달할 동안 최단거리

    즉 약간 dp처럼 생각해주면 됩니다.

    1번째 줄 cnt는 마지막에 최단거리를 저장하기 위한 변수입니다.   

    2번째 줄 end는 탐색을 완료가능한지 체크하기 위한 변수입니다.

    end가 true이면 끝까지 탐색가능하므로 cnt를 출력해주고

    end가 false이면 탐색 불가능하므로 -1을 출력해주면 됩니다.

    3번째 줄을 보면 bfs 부분의 큐 부분을 tuple로 받아주었습니다.

    {x, y, 지금까지 벽을 부순 횟수}

    10번째 줄은 탐색이 완료되었으므로 최단거리를 cnt에 저장하는 

    부분 입니다.

     

     

    이제 상하좌우로 돌아가면서 벽을 부수고 이동가능한지 그냥 이동하는지 확인해줄것입니다.

    먼저 조건이 존재합니다.

    1) 당연히 다음에 갈 위치가 0보다 작으면 안되고 n이나 m보다 크거나 같으면 안됩니다.

    2) dist[nx][ny][check] 가 값이 들어있으면 이전에 방문했다는 증거이므로 continue를 해야합니다.

     

    3) arr[nx][ny]가 0이고 check가 0이면 dist[nx][ny][0] = dist[x][y][0] +1 입니다.

    4) arr[nx][ny]가 0이고 check가 1이면 dist[nx][ny][1] = dist[x][y][1] + 1 입니다. 

    벽을 한번 부쉈기 때문에 부순 상태에서만 생각해줘야 합니다.

    5) arr[nx][ny] = 1 이고 check가 0이면 이전에 벽을 부순적이 없으므로

    벽을 부술 수 있습니다.

    따라서 dist[nx][ny][1] = dist[x][y][0] + 1 입니다.


    전체 코드입니다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<string>
    #include<stack>
    #include<queue>
    #include<deque>
    #include<cmath>
    #include<map>
    #include<set>
    #include<tuple>
    using namespace std;
    using ll = long long;
    using ull = unsigned long long;
    int on[4= { 010-1 };
    int off[4= { 10-10 };
    int arr[1001][1001];
    int dist[1001][1001][2];
    string st;
    int n, m;
    int main() {
        ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
        cin >> n >> m;
        for (int i = 0; i < n; i++) {
            cin >> st;
            for (int j = 0; j < m; j++) {
                arr[i][j] = st[j] - '0';
            }
        }
        int cnt;
        bool end = false;
        queue<tuple<int, int, int>>q;
        q.push({ 000 });
        dist[0][0][0= 1;
        while (!q.empty()) {
            int x = get<0>(q.front());
            int y = get<1>(q.front());
            int check = get<2>(q.front());
            if (x == n - 1 && y == m - 1) {
                cnt = dist[x][y][check];
                end = true;
                break;
            }
            q.pop();
            for (int i = 0; i < 4; i++) {
                int nx = x + on[i];
                int ny = y + off[i];
                if (dist[nx][ny][check])continue;
                if (nx >= 0 && ny >= 0 && nx < n && ny < m) {
                    if (!arr[nx][ny] && check ==0) {
                        dist[nx][ny][0= dist[x][y][0+ 1;
                        q.push({ nx, ny,0 });
                    }
                    else if (arr[nx][ny] == 1 && check == 0) {
                        dist[nx][ny][1= dist[x][y][0+ 1;
                        q.push({ nx, ny, 1 });
                    }
                    else if (!arr[nx][ny] && check == 1) {
                        dist[nx][ny][1= dist[x][y][1+ 1;
                        q.push({ nx, ny, 1 });
                    }
                }
            }
        }
        if (end)
            cout << cnt;
        else cout << -1;
     
        return 0;
    }
     
    cs

    '백준 문제' 카테고리의 다른 글

    백준 1939 (중량제한) c++  (0) 2022.02.26
    백준 1697 (숨바꼭질) c++  (0) 2022.02.25
    백준 1012 (유기농 배추) c++  (0) 2022.02.25
    백준 12895 (화려한 마을) c++  (0) 2022.02.23
    백준 10999 (구간 합 구하기 2)  (0) 2022.02.22
Designed by Tistory.