백준 15661. 링크와 스타트
알고리즘 기초 문제 중 브루트포스-재귀 문제(530)
1. 간단 설명
이전 문제 스타트와 링크와 유사하지만 한가지 조건만 변경되는 문제
N명의 사람들을 그냥 나누어 팀을 생성한다
즉, N/2로 나누는게 아니라
4명을 1:3으로도 나눌 수 도 있는 상황
이걸 더이상 축구라고 할 수 있을까
2. 예시
1
2
3
4
5
6
7
6
0 6 1 2 3 4
6 0 5 6 7 8
9 10 0 1 1 1
11 12 1 0 1 1
13 14 1 1 0 1
15 16 1 1 1 0
다음과 같이 주어졌을 때
(1, 2) (3, 4, 5, 6) 으로 나누면 0으로 값이 최소화 된다
3. 알고리즘
1
2
3
4
5
6
1. N과 S값들 입력받기
2. 1명, 2명, ... N-1명씩 뽑아 start_team 생성
2. 뽑히지 않은 사람들을 모아 link_team 생성
3. 각 팀의 포인트 계산
4. 두 포인트의 차를 계산하여 최소값 갱신
5. 최소값 출력
필요 변수들
- 사람 수
int N
(4 ≤ N ≤ 20, N은 짝수) - 배열
S[N][N]
각 원소는 100보다 작은 자연수 - 각 팀의 점수
start_point
,link_point
; - 최소값
int min_diff
- 팀에 속해있는지 체크할 배열
bool used[N]
: true라면 start_team, false라면 link_team
4. 소스코드
직접 구현한 조합 버전
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
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int N;
int s[21][21];
bool used[21];
vector<int> start_team, link_team;
int min_diff = 21e8;
// 각 팀의 포인트 계산
int PointCheck(vector<int>& start_team, vector<int>& link_team) {
int start_point = 0, link_point = 0;
for (int elem : start_team) {
for (int i = 0; i < N; i++) {
if(used[i]==true){
start_point += s[elem][i];
}
}
}
for (int elem : link_team) {
for (int i = 0; i < N; i++) {
if (used[i] == false) {
link_point += s[elem][i];
}
}
}
return abs(start_point - link_point);
}
void combination(int level, int start, int limit) {
if (level == limit) {
// start_team에 뽑히지 않은 선수들 link_team에 넣기
for (int i = 0; i < N; i++) {
if (used[i] == false) {
link_team.push_back(i);
}
}
min_diff = min(min_diff, PointCheck(start_team, link_team));
link_team.clear(); // 계산 후 link_team은 clear해줘야함
return;
}
for (int i = start; i < N; i++) {
used[i] = 1;
start_team.push_back(i);
combination(level + 1, i + 1, limit);
used[i] = 0;
start_team.pop_back();
}
}
int main() {
freopen_s(new FILE*, "input.txt", "r", stdin);
cin >> N;
for (int y = 0; y < N; y++){
for (int x = 0; x < N; x++) {
cin >> s[y][x];
}
}
/*****이부분이 수정됨. 몇명을 뽑을지 조합의 매개변수로 넘겨줌*****/
for (int limit = 1; limit < N; limit++) {
combination(0, 0, limit);
}
cout << min_diff;
return 0;
}
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.