ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [17471] 게리맨더링
    BOJ 2022. 1. 25. 09:22

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

     

    17471번: 게리맨더링

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

    www.acmicpc.net

    <문제>

    for(int bt=0; bt<(1<<n); bt++)로 n개중의 조합을 브루트포스하게 탐색할 수 있다.

    (어느 한쪽이) 공집합인 경우는 무의미한 문제이므로, 양쪽으 탐색범위를 한칸씩 옮겨주거나

    builtin_popcount(bt)으로 비트내 1의 수를 세고, 이것이 n혹은 0일때 return하면 되겠다.
     
     
    2번, 각 구역중 아무거나 하나 잡고 탐색을 진행한 다음 모든 노드를 방문했다면 정답을 업데이트해준다.
     
     
     

    <소스코드>

    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
    #include <bits/stdc++.h>
    using namespace std;
    const int INF = 987654321;
    int n, score[2], ans = INF, a[11];
    bool vst[11], check[11];
    vector<int> adj[11];
    int f(int cur, int bt) {
        int ret = 1;
        vst[cur] = true;
        score[check[cur] == true ? 0 : 1+= a[cur];
        for (int next : adj[cur]) {
            if (check[cur] != check[next]) continue;
            if (vst[next] == false) {
                vst[next] = true;
                ret += f(next, bt);
            }
        }
        return ret;
    }
    int main(void) {
        ios_base::sync_with_stdio(0);
        cin.tie(0);
        cin >> n;
        int i, j;
        for (i = 0; i < n; i++cin >> a[i];
        for (i = 0; i < n; i++) {
            int S;
            cin >> S;
            for (j = 0; j < S; j++) {
                int x;
                cin >> x;
                x--;
                adj[i].push_back(x);
                adj[x].push_back(i);
            }
        }
        int S = (1 << n) - 1;
        for (i = 1; i < S; i++) {
            int redIdx, blueIdx;
            memset(score, 0sizeof(score));
            memset(check, 0sizeof(check));
            memset(vst, 0sizeof(vst));
            for (j = 0; j < n; j++) {
                if (i & (1 << j)) {
                    check[j] = true;
                    redIdx = j;
                } else {
                    blueIdx = j;
                }
            }
            int ret = f(redIdx, i) + f(blueIdx, i);
            if (ret == n) ans = min(abs(score[1- score[0]), ans);
        }
        if (ans == INF) ans = -1;
        cout << ans;
        return 0;
    }
    cs

     

    'BOJ' 카테고리의 다른 글

    [16935] 배열 돌리기 3  (0) 2022.01.26
    [4375] 1  (0) 2022.01.26
    [1113] 수영장 만들기  (0) 2022.01.23
    [3687]성냥개비  (0) 2022.01.23
    [20057] 마법사 상어와 토네이도  (0) 2022.01.23

    댓글