본문 바로가기

BOJ

백준 14889 / 스타트와 링크


순열을 이용한 브루트 포스 문제.


아이디어가 필요하다. 


n의 최대값이 20이기 떄문에 20명으로 구성된 순열에 대해 모든 값을 구하는 건 시간초과가 발생한다 (20!)


그렇다면 20명을 두 팀으로 나누는 아이디어가 필요.


해결법은 0(n/2개)과 1(n/2개)로 구성된 n짜리 배열을 만들고, 


첫번째 팀은 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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include<stdio.h>
#include<iostream>
#include<vector>
#include<algorithm>
#include<math.h>
using namespace std;
 
int arr[21][21];
 
int main() {
    //freopen("Text.txt", "r", stdin);
 
    int n;
    
    cin >> n;
    int sum = 0;
    int mid = n / 2;
 
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
 
            cin >> arr[i][j];
            sum += arr[i][j];
        }
    }
 
    vector<int>member;
    member.resize(n);
 
    for (int i = 0; i < mid; i++) {
        member[i] = 1;
    }//A팀
 
    sort(member.begin(), member.end());
 
    int ans = 2000000000;
 
    do {
        vector<int>one, two;
 
        for (int i = 0; i < n; i++) {
            if (member[i] == 0) {
                one.push_back(i);
            }
            if (member[i] == 1) {
                two.push_back(i);
            }
        }
 
        int onep = 0;
        int twop = 0;
 
        for (int i = 0; i < one.size(); i++) {
            int a = one[i];
 
            for (int j = 0; j < one.size(); j++) {
                if (a != one[j]) {
                    onep += arr[a][one[j]];
                }
            }
 
 
        }
 
        for (int i = 0; i < two.size(); i++) {
            int a = two[i];
 
            for (int j = 0; j < two.size(); j++) {
                if (a != two[j]) {
                    twop += arr[a][two[j]];
                }
            }
        }
 
        int diff;
        diff = abs(onep - twop);
 
        if (ans > diff) {
            ans = diff;
        }
 
 
 
    } while (next_permutation(member.begin(), member.end()));
 
 
    cout << ans;
}
cs





재귀함수를 사용하여 팀을 나눌수도 있다.



코드 


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
#include<stdio.h>
#include<iostream>
#include<vector>
#include<algorithm>
#include<math.h>
 
using namespace std;
 
int arr[21][21];
vector<int>member;
int n;
int small = 2000000000;
 
 
int split(int idx, int cnt, vector<int>&one) {
    if (idx >= n)return 0;
    if (cnt > n / 2)return 0;
    if (cnt == n / 2) {
        int tmp = 0;
        int tmp2 = 0;
 
        vector<int>two;
 
        for (int i = 0; i < n; i++) {
            bool can = false;
            for (int j = 0; j < one.size(); j++) {
                if (i == one[j])can = true;
            }
            if (can == false) {
                two.push_back(i);
            }
        }
 
        for (int i = 0; i < one.size(); i++) {
            for (int j = 0; j < one.size(); j++) {
                if (one[i] != one[j]) {
                    tmp += arr[one[i]][one[j]];
                }
            }
        }
 
        for (int i = 0; i < two.size(); i++) {
            for (int j = 0; j < two.size(); j++) {
                if (two[i] != two[j]) {
                    tmp2 += arr[two[i]][two[j]];
                }
            }
        }
 
        int ans = 0;
        ans = abs(tmp - tmp2);
 
        if (small > ans) {
            small = ans;
        }
 
        return 0;
    }
 
    one.push_back(member[idx]);
    split(idx + 1, cnt + 1, one);
    one.pop_back();
    split(idx + 1, cnt, one);
 
}
int main() {
    //freopen("Text.txt", "r", stdin);
 
    cin >> n;
 
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cin >> arr[i][j];
        }
    }
 
    for (int i = 0; i < n; i++) {
        member.push_back(i);
    }
 
    vector<int>one;
    vector<int>result;
 
    split(00, one);
 
    cout << small;
}
cs


'BOJ' 카테고리의 다른 글

백준 9663 / N-Queen  (0) 2019.01.21
백준 1248 / 맞춰봐  (0) 2019.01.21
백준 1339 / 단어 수학  (0) 2019.01.19
백준 2529 / 부등호  (0) 2019.01.18
백준 6064 / 카잉 달력  (0) 2019.01.18