Notice
Recent Posts
Recent Comments
Link
«   2025/09   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
Archives
Today
Total
관리 메뉴

승형님의 블로그

백준 1007번, 벡터 매칭 본문

Problem Solving/백준

백준 1007번, 벡터 매칭

승형 2022. 9. 29. 13:35

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

 

1007번: 벡터 매칭

평면 상에 N개의 점이 찍혀있고, 그 점을 집합 P라고 하자. 집합 P의 벡터 매칭은 벡터의 집합인데, 모든 벡터는 집합 P의 한 점에서 시작해서, 또 다른 점에서 끝나는 벡터의 집합이다. 또, P에 속

www.acmicpc.net

 

요약

 

짝수 N개의 점이 속해있는 집합 P가 주어진다. 이때, 벡터 매칭은 집합 P 속의 한 점에서 다른 점을 잇는 벡터의 집합이다. 모든 점은 한 번만 사용된다.  벡터 매칭에 있는 모든 벡터의 합의 길이의 최솟값을 구한다.


1. 벡터의 길이는 다음과 같다. $\sqrt{( x_2 - x_1)^2 + ( y_2 - y_1)^2}$

또한, 벡터 합의 길이는 위 식에서 $x_2, y_2$ 자리에 모든 도착점 좌표들의 $x, y$값의 합을, $x_1, y_1$ 자리에 모든 시작점 좌표들의 $x, y$값의 합을 대입한 것과 같다.

 

2. 따라서, 총 N개의 점들 중 N/2개의 점들을 선택하는 모든 경우의 수에 대하여 벡터 합의 길이를 브루트포스(Brute-Force) 기법으로 구한 뒤, 그 중 최솟값을 취하여 출력하면, 문제를 해결할 수 있다.

 

3. 풀이에서 N개의 점들 중 N/2개의 점을 선택하므로 시간복잡도는 다음과 같다. O($N\times \binom{N}{\frac{N}{2}}$)

따라서, 풀이는 최대 20개의 데이터를 2초 내로 처리할 수 있다.

 

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

int T, N;
double x_input, y_input, xSum, ySum, xNegSum, yNegSum, ans; // 시작점들의 좌표값의 합 NegSum, 도착점들의 좌표값의 합 Sum
pair<double, double> point[20];
int Arr[20];

void BruteForce(int n, int k);

double VectorSum(double x, double y) { // x2-x1, y2-y1값이 들어왔을 때, 벡터합 반환
	return sqrt(x * x + y * y);
}

int main(void) {
	ios::sync_with_stdio(false);
	cout.tie(0);
	cout.precision(12);
	cout << fixed;
	cin >> T;
	for (int i = 0; i < T; i++) {
		cin >> N;
		ans = -1;
		for (int j = 0; j < N; j++)
			Arr[j] = 0;
		for (int j = 0; j < N; j++) {
			cin >> x_input >> y_input;
			point[j] = { x_input,y_input };
		}
		BruteForce(0, 0);
		cout << ans << "\n";
	}
	return 0;
}

void BruteForce(int n, int k) {
	if (k == N / 2) {
		xSum = 0;
		ySum = 0;
		xNegSum = 0;
		yNegSum = 0;
		for (int i = 0; i < N; i++) {
			if (Arr[i] == 0) {
				xSum += point[i].first;
				ySum += point[i].second;
			}
			else {
				xNegSum += point[i].first;
				yNegSum += point[i].second;
			}
		}
		if (ans == -1)
			ans = VectorSum(xSum - xNegSum, ySum - yNegSum);
		else
			ans = min(ans, VectorSum(xSum - xNegSum, ySum - yNegSum));
		return;
	}
	else if (n == N)
		return;
	else {
		for (int i = 0; i < 2; i++) {
			if (i == 0)
				BruteForce(n + 1, k);
			else {
				Arr[n] = 1;
				BruteForce(n + 1, k + 1);
				Arr[n] = 0;
			}
		}
	}
}

[raararaara 님의 피드백]

1) 실수연산에 관하여
실수 연산에는 오차가 발생할 가능성이 있기 때문에 최대한 정수형으로 연산을 진행한 뒤, 정답을 실수형으로 출력

2) 시간복잡도에 관하여
최종 시간복잡도는 O($N\times \binom{N}{\frac{N}{2}}$)이다. (반영)

 

 

Comments