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

 

아이디어

N명 중 N/2명으로 이루어진 두 팀을 어떻게 짤 것인가.

1) 재귀 (백트래킹)

2) 순열

3) 비트마스킹

방법이 있는데, 문제 출제 의도에 맞게 1번으로 문제를 풀 것이다.

 

코드

 

// BOJ 14889: 스타트와 링크
// n명 중 n/2명씩 각각 스타트팀, 링크팀으로 나눈다.
// Sij는 i번 사람과 j번 사람이 같은 팀일 때 능력치
// i번, j번이 같은 팀에 속하면 팀에 더해지는 능력치는 Sij와 Sji

#include <iostream>
#include <vector>
using namespace std;

int n;
int stats[21][21];
bool visited[21];
int result = 1e9;

// idx번 선수를 start 팀으로 뽑고, cnt는 뽑은 명수
void dfs(int idx, int cnt) {

	if (cnt == n / 2) {
		vector<int> link, start;
		for (int i = 0; i < n; i++) {
			if (visited[i] == true) // 뽑은 선수들은 스타트팀으로
				start.push_back(i);
			else
				link.push_back(i);
		}

		// 팀 간의 능력치 차
		int s_sum = 0, l_sum = 0;
		for (int i = 0; i < start.size(); i++) {
			for (int j = i + 1; j < start.size(); j++) {
				s_sum += stats[start[i]][start[j]] + stats[start[j]][start[i]];
				l_sum += stats[link[i]][link[j]] + stats[link[j]][link[i]];
			}
		}

		result = min(result, abs(s_sum - l_sum));
		return;
	}

	for (int i = idx + 1; i < n; i++) {
		if (visited[i] == false) {
			visited[i] = true;
			dfs(i, cnt + 1); // 백트래킹
			visited[i] = false;
		}
	}

}


int main()
{
	cin >> n;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			cin >> stats[i][j];
		}
	}
	dfs(0, 0);

	cout << result << "\n";
}

 

 

'알고리즘 > BOJ' 카테고리의 다른 글

백준 1978: 소수 찾기  (0) 2022.05.26
백준 1037: 약수  (0) 2022.05.26
백준 9095: 1, 2, 3 더하기  (0) 2022.02.09
백준 1182: 부분 수열의 합  (0) 2022.02.08
백준 6603 : 로또  (0) 2021.06.23

+ Recent posts