문제
리뷰
N개 중에 중복없이 N/2 개를 고른다. N과 M 문제를 다시 풀어보고 이 문제를 풀었다.
1 2 3 4 번 사람이 있으면, (총 인원 4명)
1 2 이렇게 두 명만 A팀으로 고르면 3 4 는 자동으로 B팀으로 정해진다.
그리고 1 2 를 고르면 다음에는 1 3 을 선택해야 한다.
그런데 두 명을 고르는데, 3번 사람 부터 고를 때는. 3 1 이 아니라 3 4 를 골라야 한다.
3번 사람을 고른 상태에서는, 4번 사람만 고를 수 있다.
앞서 고른 수보다 큰 수를 골라야 1 3, 3 1 처럼 중복 없이 고를 수 있다. N과 M 2에서 풀었던 코드의 구조를 따왔다. (조합)
N/2 명을 고르면 팀이 나눠진 것이다.
그 다음에는 벡터 A, B 에 숫자를 넣어두고, power 배열의 인덱스를 이용해서 능력치의 합을 구한다.
abs 함수로 절대값을 구해 처리했고 min 함수로 차이의 최소값를 계산했다.
코드
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int N;
int ch[21]; // 사람 선택 할 때 중복 방지
int map[21][21];
int mindiff = 2e9;
void go(int index, int cnt){
if(cnt == N/2){ // N/2만큼 골랐다면, 팀 나눈다.
vector<int> S, L;
int Ssum = 0, Lsum = 0;
for(int i = 0; i <N; i++){ // 팀 나눠서 벡터에 담는다.
if(ch[i]) S.push_back(i);
else L.push_back(i);
}
for(int i = 0; i < S.size(); i++){ // 팀별로 능력치 합
for(int j = i+1; j < S.size(); j++){
Ssum += (map[S[i]][S[j]] + map[S[j]][S[i]]);
Lsum += (map[L[i]][L[j]] + map[L[j]][L[i]]);
}
}
mindiff = min(mindiff, abs(Ssum-Lsum) ) ; // 차이값 갱신
return;
}
for(int i = index; i < N; i++){ // index 자리의 사람 선택
if(ch[i]) continue; // 이미 선택한 사람이면 지나감
ch[i] = 1; // 선택
go(i+1, cnt+1); // 다음 사람 선택하러 재귀호출
ch[i] = 0; // 선택 안 함.
}
}
int main(void){
cin >> N;
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++){
scanf("%d", &map[i][j]);
}
}
go(0, 0);
cout << mindiff;
return 0;
}
728x90
'알고리즘 > 백준' 카테고리의 다른 글
팩토리얼 0의 개수 백준 1676번 c++ (0) | 2020.09.12 |
---|---|
팩토리얼 백준 10872번 (0) | 2020.09.12 |
Two Dots 백준 16929번 (0) | 2020.09.09 |
섬의 개수 백준 4963번 (0) | 2020.09.08 |
나이트의 이동 백준 7562번 (0) | 2020.09.08 |