728x90
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
백트래킹으로 구현하면 되는데, 스타트팀이나 링크팀에 최소 한 명은 들어가야 한다.
그런데 1명만 들어가면 능력치를 구할 수 없다. 그러므로 2명부터~n-3명까지를 한 팀에 넣을 수 있다.
for(int i=2; i<n-1; i++) BT(0, 0, i);
BT 마지막 인자로 들어간 것은 스타트팀에 들어갈 멤버 수다.
BT를 돌면서 member 값이 되면 compareStartLink()함수로 들어가서 둘의 능력치 차이 값을 구한다.
중복을 피하기 위해 check 배열을 통해 걸러주고, 이 배열로 스타트팀에 들어갔는지 링크팀에 들어갔는지 체크할 수도 있다.
(true면 start team, false면 link team)
void BT(int cnt, int s, int member){
if(cnt == member){
compareStartLink();
return;
}
for(int i=s; i<n; i++){
if(!check[i]){
check[i] = true;
BT(cnt+1, i+1, member);
check[i] = false;
}
}
}
compareStartLink()함수에선 3가지 작업이 이루어진다.
1. check배열 속 true면 start팀에 넣어주기 / false면 link팀에 넣어주기 → 각 팀에 멤버 번호 들어감
2. 이중 for문돌면서 i번째 팀원과 j번째 팀원의 능력치 추가
3. 팀 능력 차이 최솟값 구하기
void compareStartLink(){
vector<int> start, link;
int sAB = 0, lAB = 0;
//1
for(int i=0; i<n; i++){
if(check[i]) start.push_back(i);
else link.push_back(i);
}
//2
for(int i=0; i<start.size(); i++){
for(int j=i+1; j<start.size(); j++){
sAB += (s[start[i]][start[j]] + s[start[j]][start[i]]);
}
}
for(int i=0; i<link.size(); i++){
for(int j=i+1; j<link.size(); j++){
lAB += (s[link[i]][link[j]] + s[link[j]][link[i]]);
}
}
//3
ans = min(ans, abs(sAB - lAB));
}
[전체코드]
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int n, s[21][21], ans = 40001;
bool check[21];
void compareStartLink(){
vector<int> start, link;
int sAB = 0, lAB = 0;
for(int i=0; i<n; i++){ //check를 보고 체크했으면 start, 안했으면 link
if(check[i]) start.push_back(i);
else link.push_back(i);
}
for(int i=0; i<start.size(); i++){
for(int j=i+1; j<start.size(); j++){
sAB += (s[start[i]][start[j]] + s[start[j]][start[i]]);
}
}
for(int i=0; i<link.size(); i++){
for(int j=i+1; j<link.size(); j++){
lAB += (s[link[i]][link[j]] + s[link[j]][link[i]]);
}
}
ans = min(ans, abs(sAB - lAB));
}
void BT(int cnt, int s, int member){
if(cnt == member){
compareStartLink();
return;
}
for(int i=s; i<n; i++){
if(!check[i]){
check[i] = true;
BT(cnt+1, i+1, member);
check[i] = false;
}
}
}
int main(){
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> n;
for(int i=0; i<n; i++) for(int j=0; j<n; j++) cin >> s[i][j];
for(int i=2; i<n-1; i++) BT(0, 0, i);
cout << ans << '\n';
return 0;
}
728x90
'알고리즘 > 백준' 카테고리의 다른 글
[백준/c++] 13023번: ABCDE (0) | 2022.07.30 |
---|---|
[백준/c++] 10845번: 큐 (0) | 2022.07.30 |
[백준/c++] 16198번: 에너지 모으기 (0) | 2022.07.29 |
[백준/c++] 14225번: 부분수열의 합 (0) | 2022.07.29 |
[백준/c++] 15658번: 연산자 끼워넣기 (2) (0) | 2022.07.29 |