ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백조의 호수 - 3197
    Algorithm/BOJ 2020. 3. 11. 05:37
    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
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    //3197 - 백조의 호수
     
    #include <iostream>
    #include <vector>
    #include <queue>
    using namespace std;
     
    int N, M;
    int arr[1500][1500];
    int xarr[4= {001-1};
    int yarr[4= {1-100};
    vector<int> X;
    vector<int> Y;
    queue<int> qx[2], qy[2];
    vector<vector<bool>> check;
     
    struct DisjointSet
    {
        vector<int> parent, rank;
     
        DisjointSet(int n) : parent(n), rank(n, 1)
        {
            for(int i = 0; i<n; ++i)
                parent[i] = i;
        }
     
        int find(int u)
        {
            if(u == parent[u]) return u;
            return parent[u] = find(parent[u]);
        }
     
        void merge(int u, int v)
        {
            u = find(u); v = find(v);
            if(u == v) return;
            if(rank[u] > rank[v]) swap(u, v);
            parent[u] = v;
            if(rank[u] == rank[v]) ++rank[v];
        }
    };
     
    int convert(int x, int y)
    {
        return 1 + x*M+y;
    }
     
    void aroundMerge(int x, int y, DisjointSet& set)
    {
        for(int i = 0; i<4++i)
            if(x+xarr[i] >= 0 && x+xarr[i] < N && y+yarr[i] >= 0 && y+yarr[i] < M)
                if(arr[x+xarr[i]][y+yarr[i]] == '.')
                    set.merge(convert(x, y), convert(x+xarr[i], y+yarr[i]));
    }
     
    void init(DisjointSet& set)
    {
        check = vector<vector<bool>>(N, vector<bool>(M, false));
        string s;
        for(int i = 0; i<N; ++i)
        {
            cin >> s;
            for(int j = 0; j<M; ++j)
                arr[i][j] = s[j];
        }
        for (int i = 0; i < N; ++i)
            for (int j = 0; j < M; ++j)
            {
                if (arr[i][j] != 'X')
                {
                    qx[0].push(i), qy[0].push(j), check[i][j] = true;
                    aroundMerge(i, j, set);
                }
                if (arr[i][j] == (int)'L')
                    X.push_back(i), Y.push_back(j), arr[i][j] = '.';
            }
    }
     
    void change(int x, int y, int qidx, DisjointSet& set)
    {
        if (x >= 0 && x < N && y >= 0 && y < M)
            if (arr[x][y] == 'X' && !check[x][y])
            {
               check[x][y] = true, qx[qidx].push(x), qy[qidx].push(y);
               arr[x][y] = '.';
               aroundMerge(x, y, set);
            }
    }
     
    int main()
    {
        ios_base::sync_with_stdio(0);
        cin.tie(0);
        cin >> N >> M;
        DisjointSet set(N*M+1);
        init(set);
        int ans = 0;
        int qidx = 0;
        while (true)
        {
            while (!qx[qidx].empty())
            {
                int x = qx[qidx].front();
                qx[qidx].pop();
                int y = qy[qidx].front();
                qy[qidx].pop();
                for (int k = 0; k < 4++k)
                    change(x + xarr[k], y + yarr[k], (qidx + 1) % 2, set);
            }
            ++ans;
            if(set.find(convert(X[0], Y[0])) == set.find(convert(X[1], Y[1])))
                break;
            qidx = (qidx + 1) % 2;
        }
        cout << ans;
    }
    cs

     

     

     

     

     

     

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

     

    3197번: 백조의 호수

    문제 두 마리의 백조가 호수에서 살고 있었다. 그렇지만 두 마리는 호수를 덮고 있는 빙판으로 만나지 못한다. 호수는 가로로 R, 세로로 C만큼의 직사각형 모양이다. 어떤 칸은 얼음으로 덮여있다. 호수는 차례로 녹는데, 매일 물 공간과 접촉한 모든 빙판 공간은 녹는다. 두 개의 공간이 접촉하려면 가로나 세로로 닿아 있는 것만 (대각선은 고려하지 않는다) 생각한다. 아래에는 세 가지 예가 있다. ...XXXXXX..XX.XXX ....XXXX.......XX

    www.acmicpc.net

     

     

     

     

     

     

    백조의 호수

    두가지 부분문제로 나눌수 있습니다.

     

    1. 얼음 녹이기

    queue를 이용해 인접한 얼음을 녹일수 있는 후보들을 저장해 매 단계마다

    인접 얼음을 녹이고, 녹은 얼음은 다음 단계에서 인접 얼음을 녹일수 있는 후보이니 queue에 채워 넣었습니다.

    2. 두 백조가 만나는지 확인하기

    단방향 bfs탐색으로는 시간초과가 나서 다른 방법을 찾다 union-find를 이용해 확인했습니다.

    맨 초기 단계에 연못상태에선 서로 이어진 물끼리 같은집합, 얼음은 모두 각자의 집합을 가지게 하고, 매 단계가 진행될때마다 물이된 얼음의 인접한 곳을 모두 확인해 물인것들을 모두 merge해 연결된 물들을 같은 집합에 넣고, 두 백조의 위치가 같은 집합에 포함되어 있는지 확인했습니다.

    (양방향 bfs탐색으로 해결되는지 나중에 한번 해보겠습니다..)

     

     

     

     

     

     

     

    'Algorithm > BOJ' 카테고리의 다른 글

    최소비용 구하기 2 - 11779  (0) 2020.03.12
    열쇠 - 9328  (0) 2020.03.12
    학교 탐방하기 - 13418  (2) 2020.03.11
    숫자구슬 - 2613  (0) 2020.03.10
    공유기 설치 - 2110  (0) 2020.03.10

    댓글

Designed by Tistory.