HDU6697 Closest Pair of Segments(几何数学)
来源:
HDU6697 Closest Pair of Segments
题意:
给出 n 条线段, 每个线段给出两个端点, 求任意两条线段的最短距离中最短的一个距离
代码:
#include <bits/stdc++.h>
#define endl "\n"
#define rep(i, m, n) for (int i = (m); i <= (n); ++i)
#define rrep(i, m, n) for (int i = (m); i >= (n); --i)
#define IOS ios::sync_with_stdio(0); cin.tie(0);
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e5 + 10, mod = 1e9 + 7;
int n, x[N];
struct point {
double x, y;
point operator-(const point& a) const {
return { x - a.x, y - a.y };
}
bool operator>(const point& a) const {
if (x == a.x) return y > a.y;
return x > a.x;
}
bool operator<(const point& a) const {
if (x == a.x) return y < a.y;
return x < a.x;
}
bool operator==(const point& a) const {
return x == a.x && y == a.y;
}
};
struct line { point bg, ed; }s[N];
const double eps = 1e-8;
int sign(double x) { // 判断符号
if (fabs(x) < eps) return 0;
if (x < 0) return -1;
return 1;
}
double dot(point a, point b) { return a.x * b.x + a.y * b.y; } // 点乘
double cross(point a, point b) { return a.x * b.y - b.x * a.y; } // 叉乘
double get_length(point a) { return sqrt(dot(a, a)); } // 边长
double distance_to_line(point p, point a, point b) { // 点到直线的距离
point v1 = b - a, v2 = p - a;
return fabs(cross(v1, v2) / get_length(v1));
}
double distance_to_segment(point p, point a, point b) { // 点到线段的距离
if (a == b) return get_length(p - a);
point v1 = b - a, v2 = p - a, v3 = p - b;
if (sign(dot(v1, v2)) < 0) return get_length(v2);
if (sign(dot(v1, v3)) > 0) return get_length(v3);
return distance_to_line(p, a, b);
}
double distance_segment_segment(line a, line b) { // 线段到线段的距离
double x = distance_to_segment(a.bg, b.bg, b.ed);
double y = distance_to_segment(a.ed, b.bg, b.ed);
double z = distance_to_segment(b.bg, a.bg, a.ed);
double q = distance_to_segment(b.ed, a.bg, a.ed);
if (x > y) x = y;
if (x > z) x = z;
if (x > q) x = q;
return x;
}
bool cmp(line a, line b) { return a.bg < b.bg; }
void solve() {
scanf("%d", &n);
rep(i, 1, n) {
scanf("%lf %lf %lf %lf", &s[i].bg.x, &s[i].bg.y, &s[i].ed.x, &s[i].ed.y);
if (s[i].bg > s[i].ed) swap(s[i].bg, s[i].ed);
}
sort(s + 1, s + 1 + n, cmp);
double ans = 2e15;
rep(i, 1, n) rep(j, i + 1, n) {
if (sign(s[j].bg.x - s[i].ed.x - ans) >= 0) break; // 剪枝
double res = distance_segment_segment(s[i], s[j]);
if (res < ans) ans = res;
}
printf("%.12f\n", ans);
}
int main() {
int t; cin >> t;
while (t--) solve();
return 0;
}