1007번: 벡터 매칭
평면 상에 N개의 점이 찍혀있고, 그 점을 집합 P라고 하자. 집합 P의 벡터 매칭은 벡터의 집합인데, 모든 벡터는 집합 P의 한 점에서 시작해서, 또 다른 점에서 끝나는 벡터의 집합이다. 또, P에 속
www.acmicpc.net
전형적인 백트래킹 응용문제이다.
N개의 좌표에서 N/2개의 x, y좌표 값에는 +를 붙이고, N/2개에는 -를 붙인다.
여기서 +를 붙인 좌표들은 벡터의 끝점들이고, -를 붙인 좌표들은 벡터의 시작점들이다.
이 시작점과 끝점들이 어떻게 연결되어 있는지는 길이와 관련이 없다는 점을 알고 있어야 한다.
그 후 x좌표와 y좌표를 모두 합한 후, √x2+y2를 계산한다.
경우의 수는 NCN/2개이고, 이들 중 가장 작은 값을 구하면 된다.
참고로 N=20일 때 20C10=184756이다.
아래 소스코드가 이해되지 않는다면 https://bangk00.tistory.com/6 를 보면 된다.
<소스 코드>
#include <cstdio>
#include <vector>
#include <cmath>
using namespace std;
double min1;
void selectminus(vector<pair<int,int>>&coor, vector<int>& picked, int n, int topick, int sumx, int sumy) {
if (topick == 0) {
long long x = sumx; long long y = sumy;
double result = sqrt(x*x+y*y);
if (min1 > result) min1 = result;
return;
}
int smallest = picked.empty() ? 0 : picked.back()+1;
for (int i = smallest; i < n; i++) {
picked.push_back(i);
selectminus(coor, picked, n, topick-1, sumx-2*coor[i].first, sumy-2*coor[i].second);
picked.pop_back();
}
}
int main() {
int tc;
scanf("%d", &tc);
for (int i = 0; i < tc; i++) {
min1 = 2147483647;
int n;
scanf("%d", &n);
vector<pair<int, int>> coor;
vector<int> picked;
int sumx = 0; int sumy = 0; int x,y;
for (int j = 0; j < n; j++) {
scanf("%d %d", &x, &y);
coor.push_back(make_pair(x,y));
sumx+=x; sumy+=y;
}
selectminus(coor, picked, n, n/2, sumx, sumy);
printf("%.11lf\n", min1);
}
}
이 때의 시간복잡도는 TC∗O(NCN/2) 이다.
'BOJ' 카테고리의 다른 글
[백준 1078] 뒤집음 (0) | 2022.06.27 |
---|---|
[백준 22021] 자동분무기 (0) | 2022.06.26 |
[백준 9661] 돌 게임7 (1) | 2022.06.22 |
[백준 20149] 선분 교차 3 (0) | 2022.06.18 |
[백준 12920] 평범한 배낭 2 쉬운 풀이 (1) | 2022.06.18 |