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

 

14889번: 스타트와 링크

예제 2의 경우에 (1, 3, 6), (2, 4, 5)로 팀을 나누면 되고, 예제 3의 경우에는 (1, 2, 4, 5), (3, 6, 7, 8)로 팀을 나누면 된다.

www.acmicpc.net

앞에서 dfs로 풀었던 문제이지만 비트 마스크를 연습할 겸 다시 풀어보았다.

0부터 (1<<n)-1 까지의 모든 경우를 구하고 (1 << k)를 이용해서 각 자리의 수가 0이면 해당 자리는 1번 팀에 1이면 2번 팀에 넣어주도록 했다.

000111처럼 정확히 n/2로 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
#include <iostream>
#include <vector>
using namespace std;
 
int n;
int s[20][20];
vector<int> t1;
vector<int> t2;
 
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
 
    cin >> n;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cin >> s[i][j];
        }
    }
 
    int ans = -1;
    for (int i = 0; i < (1<<n); i++) {
        
        t1.clear();
        t2.clear();
 
 
        //0인 경우 t1에 그렇지 않은 경우 t1에 넣는다.
        for (int k = 0; k < n; k++) {
            if ((i & (1 << k)) == 0) {
                t1.push_back(k);
            }
            else {
                t2.push_back(k);
            }
        }
 
 
        //팀이 반으로 나눠지지 않은 경우 skip
        if (t1.size() > n / 2continue;
        if (t2.size() > n / 2continue;
 
 
        int t1sum = 0;
        int t2sum = 0;
        for (int i = 0; i < n / 2; i++) {
            for (int j = 0; j < n / 2; j++) {
                if (i == j) continue;
                t1sum += s[t1[i]][t1[j]];
                t2sum += s[t2[i]][t2[j]];
            }
        }
 
 
        int diff = t1sum - t2sum;
        if (diff < 0) diff = -diff;
        if (ans == -1 || ans > diff) ans = diff;
 
    }
 
    cout << ans << '\n';
 
    return 0;
}
 
Colored by Color Scripter
 

'BOJ' 카테고리의 다른 글

[BOJ] 2003. 수들의 합 2  (0) 2019.07.15
[BOJ] 2748. 피보나치 수 2  (0) 2019.07.15
[BOJ] 14391. 종이 조각  (0) 2019.07.11
[BOJ] 1182. 부분수열의 합  (0) 2019.07.11
[BOJ] 11723. 집합  (0) 2019.07.11

+ Recent posts