문제의 출처는 아래와 같다.
https://www.acmicpc.net/problem/15661
이 문제는 삼성 역량테스트 기출문제인 '스타트와 링크' 의 상위호환 버전으로 문제가 조금 변형된 문제이다.
원래 문제에서는 팀을 두 그룹으로 나눌 때, 팀의 인원이 같은 즉, N/2 명으로 동일한 상태를 요구했다.
이 문제는 팀을 두 그룹으로 나눌 때, 팀의 인원이 다를 수 있다. 즉 N이 4일때 (1) , (2,3,4) 와 같이 팀의 인원이 다른 상태를 생각해야 하는 문제이다.
그래서 필자는 그룹을 나누기 위해 부분집합을 사용하였다. 부분집합을 구하면서 바로 연산을 해도 되지만 필자는 N의 부분집합을 모두 구한 상태에서 조건에 맞지 않는 부분과 이미 동일한 부분집합의 내용일때 그 경우를 바로 리턴하였다. 규칙상 N이 4일때 총 16개의 부분집합이 있는데 우리는 이중 공집합을 제외한 7개 부분만 사용하면 된다.
경우를 모두 구했으면 문제에서 요구하는대로 구현하면 된다.
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;
int n, arr[21][21], visit[21],dup,ans=987654321;
void dfs(int a, int b) {
//if (a > n / 2) return;
//printf("%d\n", b);
if (a == n+1) {
dup++;
if (dup > (pow(2.0, n) / 2)-1) return;
int val1 = 0, val2 = 0, chk1 = 0, chk2 = 0;
vector<int> t1, t2;
for (int i = 1; i <= n; i++) {
if (visit[i] == 1) t1.push_back(i);
else t2.push_back(i);
}
if (t1.empty() || t2.empty()) return;
//printf("dup: %d\n", dup);
//for (auto &i : t1) cout << i << " ";
//printf("\n");
//for (auto &i : t2) cout << i << " ";
//printf("\n\n");
for (int i = 0; i < t1.size(); i++) {
for (int j = 0; j < t1.size(); j++) {
chk1 = chk1 + arr[t1[i]][t1[j]];
}
}
for (int i = 0; i < t2.size(); i++) {
for (int j = 0; j < t2.size(); j++) {
chk2 = chk2 + arr[t2[i]][t2[j]];
}
}
//printf("%d %d", chk1, chk2);
ans = min(ans,abs(chk1 - chk2));
//printf("\n");
return;
}
visit[a] = 1;
dfs(a + 1, b);
visit[a] = 0;
dfs(a + 1, b);
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
scanf("%d", &arr[i][j]);
}
}
dfs(1, 0);
printf("%d", ans);
return 0;
}
|
cs |
'알고리즘 > 삼성 SW역량테스트' 카테고리의 다른 글
[SW expert] 3066 팀 정하기 (0) | 2022.03.16 |
---|---|
[백준] 19237 어른 상어 (0) | 2020.07.08 |
[백준] 17281 야구? (0) | 2020.05.15 |
백준[14891] 톱니바퀴 (0) | 2020.03.04 |
백준[17144] 미세먼지 안녕! (0) | 2020.02.27 |