알고리즘/삼성SW역량테스트기출

[백준 14889번 - 스타트와 링크] C++ 풀이

Ompang 2021. 9. 19. 20:12
728x90
반응형

백준 14889번.

총 n 명을 n/2 명씩 두 팀으로 나누고, 각 팀의 능력치 합을 구해서 차이를 최소로 하도록 하는 문제이다.

만약 각 팀에 3명씩 있고, 1,2,3번이 스타트팀, 3,4,5번이 링크팀이라면,

스타트팀 : S12 + S21 + S13 + S31 + S23 + S32

링크팀 : S34 + S43 + S35 + S53 + S45 + S54 가 된다.

사용한 알고리즘

- 백트래킹

 

순차적으로 탐색하면서 해당 맴버를 선택하거나/선택하지 않거나. 해서 함수를 호출하도록 했다.

depth 가 n / 2 이 되면 호출을 멈추도록 재귀를 구현하였다. 그리고 거기서 두 팀 멤버 능력치의 차를 구해서 기존거보다 더 작으면 갱신해주었다.

 

완성된 코드

#include <stdio.h>
#include <vector>
#include <stack>
#include <math.h>

using namespace std;

int n;
vector<vector<int>> v;

int ans = 1001;

void dfs(int x, vector<int> s, vector<bool> visited) {
	if (s.size() == n / 2) {
		int a1 = 0;
		int a2 = 0;
		for(int i = 0; i < s.size(); ++i) {
			for(int j = 0; j < s.size(); ++j) {
				if (s[i] != s[j]) {
					a1 += v[s[i]][s[j]];
				}
			}
		}
		vector<int> v2;
		for(int i = 0; i < n; ++i) {
			if (visited[i] == false) {
				v2.push_back(i);
			}
		}
		for(int i = 0; i < v2.size(); ++i) {
			for(int j = 0; j < v2.size(); ++j) {
				if (i != j) {
					a2 += v[v2[i]][v2[j]];
				}
			}
		}
		ans = (ans > abs(a1 - a2)) ? abs(a1 - a2) : ans;
		return;
	} else {
		for(int i = x; i < n; ++i) {
			s.push_back(i);
			visited[i] = true;
			dfs(i + 1, s, visited);
			visited[i] = false;
			s.pop_back();
		}
	}
}

int main() {
	scanf("%d", &n);
	vector<bool> visited;
	v.assign(n + 1, vector<int>(n + 1));
	visited.assign(n + 1, false);
	for(int i = 0; i < n; ++i) {
		for(int j = 0; j < n; ++j) {
			scanf("%d", &v[i][j]);
		}
	}
	vector<int> s;
	dfs(0, s, visited);
	printf("%d\n", ans);
}
728x90