코딩문제 풀이

14889번 스타트와 링크

student513 2020. 1. 16. 17:52
 

14889번: 스타트와 링크

예제 2의 경우에 (1, 3, 6), (2, 4, 5)로 팀을 나누면 되고, 예제 3의 경우에는 (1, 2, 4, 5), (3, 6, 7, 8)로 팀을 나누면 된다.

www.acmicpc.net

전형적인 브루트포스 문제.

 

이전에 풀었던 N과 M문제를 참조하였다.

 

1. N명의 선수를 두 팀으로 나누기  : n C n/2

2. 각 팀을 2인1조로 구성하여 총 전력을 구하기 : n/2 C n

 

크게 두 분으로 나뉘어 있다.

 

막혔던 부분은 브루트포스 재귀문을 이용해 어떻게 두 팀을 동시에 구성할 것이냐에 관한 것이었다.

 

재귀를 돌릴 때마다 start팀과 link팀에 동시에 완전탐색을 통한 팀구성을 해야하나 싶었지만

 

두 팀은 배타적이기 때문에 한 팀의 정보만 저장해주면 다른 팀의 구성원도 동시에 결정되기 때문에

 

여느 브루트포스 문제와 다를 것이 없었다.

 

재귀조건을 if(!member[i])로만 설정하니 이전에 등장한 조합이 또 등장하여 시간초과로 터져버렸기 때문에 

 

N과M에서 사용한 기법을 참조하여 arr라는 배열을 추가하여 

 

중복된 조합을 걸러낼 수 있었다.

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

int N, cnt;
int map[21][21];
vector<int> start;
vector<int> link;
bool member[21];
int start_scr;
int link_scr;
vector<int> s_scr;
vector<int> l_scr;
vector<int> t_scr;
int arr[11];

void print_team() {//디버깅용
	cout << '\n';
	for (int i = 0; i < start.size(); i++) {
		cout << start[i] << " ";
	}
	cout << '\n';
	for (int i = 0; i < link.size(); i++) {
		cout << link[i] << " ";
	}
	cout << '\n';
}

void make_duo() {//팀 전력 구하기
	start_scr = link_scr = 0;
	for (int i = 0; i < start.size(); i++) {
		for (int j = 0; j < start.size(); j++) {
			if (i != j) {
				start_scr += map[start[i]][start[j]];
				start_scr += map[start[j]][start[i]];
			}
		}
	}

	for (int i = 0; i < link.size(); i++) {
		for (int j = 0; j < link.size(); j++) {
			if (i != j) {
				link_scr += map[link[i]][link[j]];
				link_scr += map[link[j]][link[i]];
			}
		}
	}

	s_scr.push_back(start_scr);
	l_scr.push_back(link_scr);
}

void make_team(int cnt) {//팀 구성
	if (cnt == N / 2) {
		start.clear();
		link.clear();
		for (int i = 0; i < N; i++) {
			if (member[i]) {
				start.push_back(i);
			}
			else {
				link.push_back(i);
			}
		}
		//for (int i = 0; i < 3; i++) { cout << arr[i] << " "; }
		//cout << '\n';
		make_duo();
		//print_team();
		return;
	}
	for (int i = 0; i < N; i++) {
		if (!member[i] && arr[cnt-1] <= i) {
			arr[cnt]=i;
			member[i] = true;
			make_team(cnt + 1);
			member[i] = false;
		}
		else if(cnt==0) {
			arr[cnt] = i;
			member[i] = true;
			make_team(cnt + 1);
			member[i] = false;
		}
	}
}

int main() {
	cin >> N;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			cin >> map[i][j];
		}
	}

	make_team(0);

	for (int i = 0; i < s_scr.size(); i++) {
		int temp = abs(s_scr[i] - l_scr[i]);
		t_scr.push_back(temp);
	}
	sort(t_scr.begin(), t_scr.end());

	cout << t_scr.front()/2;
	return 0;
}

'코딩문제 풀이' 카테고리의 다른 글

14891번 톱니바퀴  (0) 2020.01.21
14888번 연산자 끼워넣기  (0) 2020.01.17
14503번 로봇 청소기  (0) 2020.01.15
백준 14502번 연구소  (0) 2020.01.14
백준 14890번 경사로  (0) 2020.01.08