반응형
문제 : https://www.acmicpc.net/problem/14889
서론
완전탐색 문제.
풀이
스타트와 링크팀을 만들 수 있는 모든 경우의 수를 재귀를 이용한 완전탐색으로 구현한다.
그리고 팀의 구분은 배열로 만들 수 있는데, 하나의 배열에 1의 팀과 0의 팀으로 구분할 수 있다.
team{1, 1, 0, 0}은 1,2가 1팀, 3,4가 0팀
team{1, 0, 0, 1}은 1,4가 1팀, 2,3이 0팀
void dfs(int idx, int cnt, bool tf){
if(tf == true) team[idx] = 1;
else team[idx] = 0;
if(cnt == n/2) 팀별 계산하고 리턴;
else if(idx == n) return
dfs(idx+1, cnt+1, true);
dfs(idx+1, cnt, false);
}
그 후 1팀의 능력치 합은 아래 코드와 같고 0팀의 합도 같은 원리이며 얻어진 합으로 1팀과 0팀의 차이값을 계산한다. 이 과정을 모든 경우의 수에 실행한다.
for (int i = 1; i <= n; i++) {
if (team[i] == 0) continue;
for (int j = 1; j <= n; j++) {
if (i != j && team[j] != 0) {
sumA += map[i][j];
}
}
}
team 배열의 왼쪽부터 순차적으로 탐색하며 한 팀원을 선택하고 그 팀원과 같은 팀에 속한 팀원들의 능력치들을 다 더한다.
예를들어 1번과 3번이 같은 팀이라면
1번을 선택했을때 같은 팀에 속한 능력치들을 더하는 과정에서 S13이 더해지고
3번을 선택했을때 같은 팀에 속한 능력치들을 더하는 과정에서 S31이 더해진다.
구현
// c++
#include <iostream>
#include <algorithm>
using namespace std;
int map[100][100];
int team[101];
int n;
int result = 0x7f7f7f7f;
void init() {
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
cin >> map[i][j];
}
}
}
int cal() {
int sumA = 0;
int sumB = 0;
for (int i = 1; i <= n; i++) {
if (team[i] == 0) continue;
for (int j = 1; j <= n; j++) {
if (i != j && team[j] != 0) {
sumA += map[i][j];
}
}
}
for (int i = 1; i <= n; i++) {
if (team[i] == 1) continue;
for (int j = 1; j <= n; j++) {
if (i != j && team[j] != 1) {
sumB += map[i][j];
}
}
}
//cout << sumA << " " << sumB << endl;
return abs(sumA - sumB);
}
void dfs(int idx, int cnt, bool tf) {
if (tf == true) team[idx] = 1;
else team[idx] = 0;
if (cnt == n / 2) {
/*
cout << idx << endl;
for (int i = 1; i <= n; i++) {
cout << team[i] << " ";
}
cout << endl;
*/
result = min(result, cal());
return;
}
else if (idx == n) {
return;
}
dfs(idx + 1, cnt + 1, true);
dfs(idx + 1, cnt, false);
return;
}
int main() {
init();
dfs(0, 0, 1);
cout << result;
}
최근댓글