※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 3688번 문제인 래프팅 디자인이다.
문제는 아래 링크를 확인하자.

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

 

주어지는 다각형이 볼록다각형이 아닐 수 있음에 유의하자.

 

내부 다각형과 외부 다각형 사이의 최단거리를 구하면 문제를 해결할 수 있을 것이다. 이 값을 어떻게 구할 수 있을까?

 

다각형은 선분의 집합으로 나타낼 수 있으므로, 구하고자 하는 값은 "내부 다각형을 구성하는 선분 집합"의 원소와 "외부 다각형을 구성하는 선분 집합"의 원소 사이의 최솟값으로 생각할 수 있다. 여기에서 실제로는 튜브가 동시에 접하지 못할 두 선분쌍도 골라질 수 있지만, 그러한 선분쌍의 경우 튜브가 더 작아야하게끔 하는 다각형을 구성하는 다른 선분이 존재함을 생각하면 위의 계산으로 답을 얻을 수 있다는 사실이 변하지 않는다는 점을 알 수 있다.

 

가능한 모든 내부 다각형의 선분과 외부 다각형의 선분의 쌍에 대하여 두 선분 사이의 거리의 최솟값들 중 가장 작은 값을 구해 문제를 해결하자.

 

아래는 제출한 소스코드이다.

#include <iostream>
#include <cmath>
using namespace std;
typedef long double ld;

ld func(ld X1, ld Y1, ld X2, ld Y2, ld X3, ld Y3, ld X4, ld Y4) {
	ld ret = 1000000007;
	ret = min(ret, hypotl(X1 - X3, Y1 - Y3));
	ret = min(ret, hypotl(X1 - X4, Y1 - Y4));
	ret = min(ret, hypotl(X2 - X3, Y2 - Y3));
	ret = min(ret, hypotl(X2 - X4, Y2 - Y4));

	ld P1, P2, Q1, Q2, R1, R2, P, Q, R;
	P1 = X3, P2 = Y3, Q1 = X1, Q2 = Y1, R1 = X2, R2 = Y2;
	P = (Q1 - R1) * (Q1 - R1) + (Q2 - R2) * (Q2 - R2);
	Q = (P1 - R1) * (P1 - R1) + (P2 - R2) * (P2 - R2);
	R = (P1 - Q1) * (P1 - Q1) + (P2 - Q2) * (P2 - Q2);
	if (Q < P + R && R < P + Q) {
		ld A = P1 * Q2 + Q1 * R2 + R1 * P2 - P2 * Q1 - Q2 * R1 - R2 * P1;
		ld val = abs(A / sqrtl(P));
		ret = min(ret, val);
	}

	P1 = X4, P2 = Y4, Q1 = X1, Q2 = Y1, R1 = X2, R2 = Y2;
	P = (Q1 - R1) * (Q1 - R1) + (Q2 - R2) * (Q2 - R2);
	Q = (P1 - R1) * (P1 - R1) + (P2 - R2) * (P2 - R2);
	R = (P1 - Q1) * (P1 - Q1) + (P2 - Q2) * (P2 - Q2);
	if (Q < P + R && R < P + Q) {
		ld A = P1 * Q2 + Q1 * R2 + R1 * P2 - P2 * Q1 - Q2 * R1 - R2 * P1;
		ld val = abs(A / sqrtl(P));
		ret = min(ret, val);
	}

	P1 = X1, P2 = Y1, Q1 = X3, Q2 = Y3, R1 = X4, R2 = Y4;
	P = (Q1 - R1) * (Q1 - R1) + (Q2 - R2) * (Q2 - R2);
	Q = (P1 - R1) * (P1 - R1) + (P2 - R2) * (P2 - R2);
	R = (P1 - Q1) * (P1 - Q1) + (P2 - Q2) * (P2 - Q2);
	if (Q < P + R && R < P + Q) {
		ld A = P1 * Q2 + Q1 * R2 + R1 * P2 - P2 * Q1 - Q2 * R1 - R2 * P1;
		ld val = abs(A / sqrtl(P));
		ret = min(ret, val);
	}

	P1 = X2, P2 = Y2, Q1 = X3, Q2 = Y3, R1 = X4, R2 = Y4;
	P = (Q1 - R1) * (Q1 - R1) + (Q2 - R2) * (Q2 - R2);
	Q = (P1 - R1) * (P1 - R1) + (P2 - R2) * (P2 - R2);
	R = (P1 - Q1) * (P1 - Q1) + (P2 - Q2) * (P2 - Q2);
	if (Q < P + R && R < P + Q) {
		ld A = P1 * Q2 + Q1 * R2 + R1 * P2 - P2 * Q1 - Q2 * R1 - R2 * P1;
		ld val = abs(A / sqrtl(P));
		ret = min(ret, val);
	}

	return ret;
}

int N, M;
ld A[101][2], B[101][2];

void solve() {
	ld ans = 1000000007;
	cin >> N;
	for (int i = 0; i < N; i++) cin >> A[i][0] >> A[i][1];
	A[N][0] = A[0][0], A[N][1] = A[0][1];
	cin >> M;
	for (int i = 0; i < M; i++) cin >> B[i][0] >> B[i][1];
	B[M][0] = B[0][0], B[M][1] = B[0][1];

	for (int i = 0; i < N; i++) {
		ld X1 = A[i][0], Y1 = A[i][1], X2 = A[i + 1][0], Y2 = A[i + 1][1];
		for (int j = 0; j < M; j++) {
			ld X3 = B[j][0], Y3 = B[j][1], X4 = B[j + 1][0], Y4 = B[j + 1][1];
			ans = min(ans, func(X1, Y1, X2, Y2, X3, Y3, X4, Y4));
		}
	}

	cout << ans / 2 << '\n';
}

int T;

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	cout << fixed;
	cout.precision(10);

	cin >> T;
	while (T--) solve();
}

 

랜덤 마라톤 (Beta) · 코스 3 H번

728x90

'BOJ' 카테고리의 다른 글

[BOJ 13352 // C++] 석양이 진다...  (0) 2024.06.22
[BOJ 2187 // C++] 점 고르기  (0) 2024.06.21
[BOJ 22683 // C++] Square Route  (1) 2024.06.19
[BOJ 25140 // C++] KLIZA  (0) 2024.06.18
[BOJ 20046 // C++] Road Reconstruction  (0) 2024.06.17

+ Recent posts