Processing math: 100%

 

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);
    }
}

이 때의 시간복잡도는 TCO(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

+ Recent posts