ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 게리맨더링
    백준알고리즘 2019. 9. 20. 18:05

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

     

    17471번: 게리맨더링

    선거구를 [1, 4], [2, 3, 5, 6]으로 나누면 각 선거구의 인구는 9, 8이 된다. 인구 차이는 1이고, 이 값보다 더 작은 값으로 선거구를 나눌 수는 없다.

    www.acmicpc.net

    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
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    #include<iostream>
    #include<vector>
    #include<queue>
    #include<cstring>
     
    using namespace std;
     
    int n;
    int peo[11];
    bool d[11];
    int sum = 987654321;
    bool gett =false;
    vector<int> map[11];
    bool vect(vector<int>&a, int x){
        for(int i = 0; i<a.size(); i++){
            if(x == a[i]) {
                return true;
            }
        }
        return false;
    }
     
    bool bfs(vector<int>& a){
        bool x[11];
        memset(x,falsesizeof(x));
        if(a.size() >0) {
            queue<int> q;
     
            q.push(a[0]);
            x[a[0]] = true;
     
            while(!q.empty()){
                int X = q.front(); q.pop();
                for(int i = 0; i < map[X].size(); i++){
                    if(vect(a,map[X][i])) {
                        if (x[map[X][i]] == false) {
                            x[map[X][i]] = true;
                            q.push(map[X][i]);
                        }
                    }
                }
            }
        }
        for(int i = 0; i<a.size(); i++){
            if(x[a[i]] == false)
                return false;
        }
        return true;
     
    }
     
    void divide(vector<int>& a, vector<int>&b, int cnt ){
        if(cnt == n+1){
            if(a.size() == 0 ||b.size() == 0){
                return;
            }
            else{
                int ans1 = 0int ans2 = 0;
                if(bfs(a) &&bfs(b)) {
                    for (int i = 0; i < a.size(); i++) {
                        ans1 += peo[a[i]];
                    }
                    for (int i = 0; i < b.size(); i++) {
                        ans2 += peo[b[i]];
                    }
                    int ans = ans1 - ans2;
                    if (ans < 0) ans = -1 * ans;
                    if (sum > ans) {
                       /* cout << "A" << '\n';
                        for (int i = 0; i < a.size(); i++) {
                            cout << a[i] << ' ';
                        }
                        cout << '\n';
                        cout << 'B' << '\n';
                        for (int i = 0; i < b.size(); i++) {
                            cout << b[i] << ' ';
                        }
                        cout << '\n';
                        cout << ans << '\n';*/
                        sum = ans;
                        gett = true;
                    }
                    return;
                }
            }
        }
        else{
            if(d[cnt] == false) {
                    a.push_back(cnt);
                    d[cnt] = true;
                    divide(a, b, cnt + 1);
                    a.pop_back();
                    d[cnt] = false;
     
                    b.push_back(cnt);
                    d[cnt] = true;
                    divide(a, b, cnt + 1);
                    b.pop_back();
                    d[cnt] = false;
     
            }
        }
    }
     
    int main(){
        ios_base::sync_with_stdio(0);
        cin.tie(0);
        cin>>n;
        for(int i = 1; i <= n; i++){
            cin>>peo[i];
        }
     
        for(int i = 1; i <= n; i++){
            int cos,y;
            cin>>cos;
            for(int j = 0; j < cos; j++){
                cin>>y;
                map[i].push_back(y);
            }
        }
     
        vector<int> a,b;
        divide(a,b,1);
        if(gett)
            cout<<sum<<'\n';
        else
            cout<<-1<<'\n';
     
        return 0;
     
    }
    http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
     

    그렇게 전형적이지만은 않은 BFS문제

    배열의크기자체가 굉장히작기 때문에 모든것을 다해봐도 괜찮았을문제다.

    풀이방법은 다음과 같다.

    1. 팀(구역) 나누기

    2.나눠진 팀 검사하기

    - 비어있는팀이 있을시 - > return

    - BFS통해서 팀끼리 이어져있는지 확인 -> 아닐시 return

     

    3. 합 구하고 계산하기

     

     

    메커니즘 자체는 어렵지 않았다.

    함정이 하나있다면, 백트랙킹처럼 검사를 하나하나 다하면서 넣는것보다는 배열이작기때문에 

    팀을짜고 검사를하는게 맞기도하고, 다짜고 검사하는 큰이유는

    검사하면서 넣으면 문제에서 주어지는 1 3 4 , 2 4 5같이 하나씩 떨어져있는것들을 만들수없다.

     

    참고로 역량테스트 1번문제와 유사하다.

    '백준알고리즘' 카테고리의 다른 글

    신기한 소수  (0) 2019.09.21
    사다리 조작  (0) 2019.09.21
    상범 빌딩  (0) 2019.09.17
    역사  (0) 2019.09.17
    경로찾기  (0) 2019.09.16

    댓글

Designed by Tistory.