Topic links: point I ah ╭ (╯ ^ ╰) ╮
Subject to the effect:
begging nearest line segment of line segments
Problem-solving ideas:
From the enumeration every two segments of violence
but to sort the left endpoint of each segment of
the right end point if the left segment
and the right segment of the left end point
value is greater than the
directly
, can be optimized so that even
seconds
Core: recent line segment optimization
#include<bits/stdc++.h>
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
const double eps = 1e-6;
struct point {
double x, y;
point() {}
point(double X, double Y) {
x = X, y = Y;
}
point operator - (const point &A) {
return point(x-A.x, y-A.y);
}
bool operator < (const point &A)const {
if(x == A.x) return y < A.y;
return x < A.x;
}
} ;
inline int dcmp(double x) {
if(fabs(x) < eps) return 0;
return x < 0 ? -1 : 1;
}
inline double cross(point A, point B) { // 叉积
return A.x*B.y - B.x*A.y;
}
inline double dot(point A, point B) { // 点积
return A.x*B.x + B.y*A.y;
}
double getdis(point a, point b) { // 两点距离
return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}
struct Line {
point s, e;
Line() {}
Line(point S, point E) {
s = S, e = E;
}
double length() {
return getdis(s, e);
}
};
//点到直线距离
inline double point_to_line(point p, Line a) {
return fabs(cross(p-a.s, a.e-a.s) / a.length());
}
//点到线段距离
inline double point_to_seg(point p, Line a) {
if(dcmp(dot(p-a.s, a.e-a.s))<0 || dcmp(dot(p-a.e, a.s-a.e))<0)
return min(getdis(p, a.e), getdis(p, a.s));
return point_to_line(p, a);
}
//线段到线段的距离
inline double seg_to_seg(Line u, Line v) {
return min( min(point_to_seg(u.s, v), point_to_seg(u.e, v)),\
min( point_to_seg(v.s, u), point_to_seg(v.e, u)) );
}
bool cmp(const Line &u, const Line &v) {
return u.s < v.s;
}
const int maxn = 1e4 + 5;
int T, n;
Line line[maxn];
int main() {
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
for(int i=1; i<=n; i++) {
scanf("%lf%lf", &line[i].s.x, &line[i].s.y);
scanf("%lf%lf", &line[i].e.x, &line[i].e.y);
if(line[i].e < line[i].s) swap(line[i].s, line[i].e);
}
sort(line+1, line+1+n, cmp);
double ans = 1e10;
for(int i=1; i<=n; i++) {
for(int j=i+1; j<=n; j++) {
if(dcmp(line[j].s.x-line[i].e.x - ans) > 0) break;
ans = min(ans, seg_to_seg(line[i], line[j]));
}
}
printf("%.9f\n", ans);
}
}