14889번: 스타트와 링크
예제 2의 경우에 (1, 3, 6), (2, 4, 5)로 팀을 나누면 되고, 예제 3의 경우에는 (1, 2, 4, 5), (3, 6, 7, 8)로 팀을 나누면 된다.
www.acmicpc.net
- 팀을 정할 때에는 팀원의 수가 다 찰 때 까지 백트래킹을 통해 1팀에서 한명씩 뽑아나간다.
- 팀원 (0,1) 과 (1,0) 을 뽑는 경우는 같은 경우기 때문에, 반복문의 시작 인덱스를 직전 호출에서 넘겨주어야 한다.
- 1팀의 팀원 수가 다 찼다면, 나머지 팀원들을 2팀으로 지정한다.
- 행렬이 대칭이 아니기 때문에, 팀의 능력치는 각 팀별로 2명씩 뽑았을 때 가능한 모든 조합들을 인덱싱해서 더해야 한다.
#include <iostream>
using namespace std;
int n, team_n, answer = 10e8;
int info[20][20];
bool visited[20];
int team[2][10];
int power(int t) // t 로 주어지는 팀의 능력치를 반환
{
int ret = 0;
for(int i = 0 ; i < team_n - 1 ; i++) // 팀을 2중반복문으로 돌리면서 능력치를 다 더함
{
for(int j = i + 1 ; j < team_n ; j++)
{
ret += info[team[t][i]][team[t][j]];
ret += info[team[t][j]][team[t][i]];
}
}
return ret;
}
void check(int start, int size) // 백트래킹
{
if(size == team_n)
{
for(int i = 0, idx = 0 ; i < n ; i++) // 팀1 이 구해졌기 때문에, 팀2 를 그에 맞게 구하고
{
if(visited[i] == false)
team[1][idx++] = i;
}
int value = abs(power(0) - power(1)); // 두 팀 능력치의 차이를 구해서
if(value < answer) answer = value; // 최솟값 갱신
return;
}
for(int i = start + 1 ; i < n ; i++) // 팀1 의 멤버들을 뽑는 과정
{
if(visited[i] == false)
{
visited[i] = true;
team[0][size] = i; // 팀1 의 멤버목록에 추가해주고
check(i, size + 1); // 재귀호출
visited[i] = false;
}
}
}
int main(void)
{
cin >> n;
team_n = n / 2;
for(int r = 0 ; r < n ; r++)
for(int c = 0 ; c < n ; c++)
cin >> info[r][c];
check(-1, 0);
cout << answer << endl;
}
- 2등 소스코드 참고 : www.acmicpc.net/source/21428017
- 백트래킹을 팀원의 수가 아니라, 1 부터 N 까지의 사람들을 차례대로 어느 팀에서 뽑아가는지를 결정하는데 사용했다.
int main(void)
{
cin >> n;
team_n = n / 2;
for(int r = 0 ; r < n ; r++)
for(int c = 0 ; c < n ; c++)
cin >> info[r][c];
check(-1, 0);
cout << answer << endl;
}
#include <cstdio>
int n;
int a[20][20], t1[10], t2[10];
int an, bn, ans = 1e5;
void go(int x)
{
if(ans == 0) return;
if(x == n)
{
int s1 = 0, s2 = 0;
for(int i = 0 ; i < n / 2 - 1 ; i++)
{
for(int j = i + 1 ; j < n / 2 ; j++)
{
s1 += a[t1[i]][t1[j]] + a[t1[j]][t1[i]];
s2 += a[t2[i]][t2[j]] + a[t2[j]][t2[i]];
}
}
int temp = (s1 - s2 > 0) ? (s1 - s2) : (s2 - s1);
ans = ans > temp ? temp : ans;
return;
}
if(an < n / 2)
{
t1[an++] = x;
go(x + 1);
an--;
}
if(bn < n / 2)
{
t2[bn++] = x;
go(x + 1);
bn--;
}
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
scanf("%d", &a[i][j]);
go(0);
printf("%d", ans);
}
'PS > BOJ' 카테고리의 다른 글
[백준] 1904.cpp : 01타일 (0) | 2020.09.09 |
---|---|
[백준] 1158.cpp : 요세푸스 문제 (0) | 2020.09.08 |
[백준] 10815.cpp : 숫자 카드 (0) | 2020.09.06 |
[백준] 14888.cpp : 연산자 끼워넣기 (0) | 2020.09.05 |
[백준] 2193.cpp : 이친수 (0) | 2020.09.04 |