Baekjoon Review

[Gold 5] 15661 링크와 스타트

hanseongbugi 2024. 3. 3. 17:26

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

 

15661번: 링크와 스타트

첫째 줄에 N(4 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에 S가 주어진다. 각 줄은 N개의 수로 이루어져 있고, i번 줄의 j번째 수는 Sij 이다. Sii는 항상 0이고, 나머지 Sij는 1보다 크거나 같고, 100

www.acmicpc.net

 

이 문제는 조합을 이용한 완전 탐색 문제이다.

 

팀은 2개로 이루어져 있고, 팀의 최소 인원은 2명이다.

따라서 2명의 묶음이 만들어 졌을 때 팀원의 능력치를 더한 후

2개의 팀간의 능력치 차이의 절대 값을 구하면 된다.

 

팀 간의 묶음은 다음과 같다.

1 1 1 1 
1 1 1 0 
1 1 0 1 
1 1 0 0 
1 0 1 1 
1 0 1 0 
1 0 0 1 
1 0 0 0 
0 1 1 1 
0 1 1 0 
0 1 0 1 
0 1 0 0 
0 0 1 1 
0 0 1 0 
0 0 0 1 
0 0 0 0

이중 최소 값은 2개의 팀 간의 능력치 합이 최소인 경우에만 가능하고 1팀에 3명이 몰리는 순간은 모두 최소가 아니게 된다.

따라서 팀간에 균형있게 만들어졌는지는 판단하지 않아도 된다. 

 

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

int N;
int ability[21][21];
bool visited[21];
int result = 987654321;

int calc(){
    int counter1 = 0;
    int counter2 = 0;
    for(int i = 0;i<N-1;i++){
        for(int j = i+1;j<N;j++){
            if(visited[i] && visited[j])
                counter1 += ability[i][j] + ability[j][i];
            
            else if(!visited[i]&&!visited[j])
                counter2 += ability[i][j] + ability[j][i];
        }
    }
    return abs(counter1- counter2);
}

void combination(int counter){
    if(counter==N){
        result = min(result, calc());
        return;
    }
    visited[counter] = true;
    combination(counter+1);
    visited[counter] = false;
    combination(counter+1);
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	
    cin>>N;

    for(int i = 0;i<N;i++){
        for(int j = 0;j<N;j++)
            cin>>ability[i][j];
    }
    combination(0);
	cout<<result<<'\n';

	return 0;
}