ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [17267] 상남자
    BOJ 2021. 11. 3. 06:55

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

     

    17267번: 상남자

    CTP의 대표 상남자 영조는 자유롭게 이동하는 것을 좋아한다. 그렇지만 영조는 상남자이기 때문에 위아래로만 간다. 따라서 위, 아래로는 얼마든지 이동할 수 있지만 왼쪽, 오른쪽으로는 이동하

    www.acmicpc.net

    <문제>

    정점의 재방문을 허용할 필요성이 있을 수 있겠다는 생각이 들 수 있지만...

    그렇다고 visit[N][M][L][R]처럼 만들수도 없다. 이렇게 만들면 배열 갯수만 1000^4개다.

     

    어떤 정점을 이미 방문했더라도 그때에 비해서 적은 L, R로 이동한다면 더 멀리 갈 수 있다는 부분을 염두해야 한다.

    좌나 우로 이동하는것이 가중치가 1, 상이나 하로 이동하는것이 가중치가 0이라는 것에 착안하여

    0-1 BFS로 모든 정점을 최적의 L, R 이동횟수로 접근이 가능하다.

    덱을 사용할 수도 있고, 가중치가 0인 경우는 현재 정점과 같은 열뿐이므로 단순히 while()로 구현할수도 있다.

     

    <소스코드>

    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
    #include <bits/stdc++.h>
    using namespace std;
    int n, m, l, r, sy, sx, a[1001][1001], dy[4= {1-100},
                                           dx[4= {001-1};
    bool visited[1001][1001];
    typedef struct {
        int y, x, left, right;
    } state;
    queue<state> q;
    int main(void) {
        ios_base::sync_with_stdio(false);
        cin.tie(0);
        cout.tie(0);
        cin >> n >> m >> l >> r;
        int i, j;
        for (i = 0; i < n; i++) {
            string s;
            cin >> s;
            for (j = 0; j < m; j++) {
                if (s[j] == '2') {
                    sy = i;
                    sx = j;
                    q.push({sy, sx, 00});
                    visited[sy][sx] = true;
                    a[sy][sx] = 0;
                } else
                    a[i][j] = s[j] - '0';
            }
        }
        while (!q.empty()) {
            auto cur = q.front();
            q.pop();
            for (i = 0; i < 2; i++) {
                int y = cur.y;
                int x = cur.x;
                while (1) {
                    y += dy[i];
                    if (y < 0 || y >= n) break;
                    if (a[y][x] == 1break;
                    if (visited[y][x] == false) {
                        visited[y][x] = true;
                        q.push({y, x, cur.left, cur.right});
                    }
                }
            }
            for (i = 2; i < 4; i++) {
                int y = cur.y + dy[i];
                int x = cur.x + dx[i];
                if (y < 0 || x < 0 || y >= n || x >= m) continue;
                if (a[y][x] == 1continue;
                if (i == 2 && cur.right == r) continue;
                if (i == 3 && cur.left == l) continue;
                if (visited[y][x] == false) {
                    visited[y][x] = true;
                    if (i == 2)
                        q.push({y, x, cur.left, cur.right + 1});
                    else
                        q.push({y, x, cur.left + 1, cur.right});
                }
            }
        }
        int cnt = 0;
        for (i = 0; i < n; i++)
            for (j = 0; j < m; j++)
                if (visited[i][j]) cnt++;
        cout << cnt;
        return 0;
    }
    cs

     

    'BOJ' 카테고리의 다른 글

    [1700] 멀티탭 스케줄링  (0) 2021.11.04
    [13907] 세금  (0) 2021.11.03
    [2842] 집배원 한상덕  (0) 2021.11.02
    [1311] 할 일 정하기 1  (0) 2021.11.01
    [2302] 극장 좌석  (0) 2021.11.01

    댓글