HDU 6697 Closest Pair of Segments(线段距离)
首先最容易想到的就是N2暴力枚举所有线段去找最小值,但是这样会做了许多无用功。我们可以先对线段排序,使得线段最左侧的端点按照x轴y轴排序,然后我们可以限定在这个线段的矩形框内的所有线段才有可能产生最小值,每次查询对于第i条线段的最近距离,如果第j条线段的最左侧点的x与第i条线段的最右侧点的x差值大于ans,那么可以直接break,之后枚举是没有任何意义的,一定会大于ans,所以加了这部分剪枝复杂度就压缩了很大部分。
1 // ——By DD_BOND 2 3 //#include<bits/stdc++.h> 4 //#include<unordered_map> 5 //#include<unordered_set> 6 #include<functional> 7 #include<algorithm> 8 #include<iostream> 9 //#include<ext/rope> 10 #include<iomanip> 11 #include<climits> 12 #include<cstring> 13 #include<cstdlib> 14 #include<cstddef> 15 #include<cstdio> 16 #include<memory> 17 #include<vector> 18 #include<cctype> 19 #include<string> 20 #include<cmath> 21 #include<queue> 22 #include<deque> 23 #include<ctime> 24 #include<stack> 25 #include<map> 26 #include<set> 27 28 #define fi first 29 #define se second 30 #define MP make_pair 31 #define pb push_back 32 33 #pragma GCC optimize(3) 34 #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") 35 36 using namespace std; 37 38 typedef long long ll; 39 40 const int MAXN=1e5+10; 41 const double eps=1e-8; 42 const double pi=acos(-1.0); 43 const ll INF=0x3f3f3f3f3f3f3f3f; 44 45 inline int dcmp(double x){ 46 if(fabs(x)<eps) return 0; 47 return (x>0? 1: -1); 48 } 49 50 inline double sqr(double x){ return x*x; } 51 52 struct Point{ 53 double x,y; int id; 54 Point(){ x=0,y=0; } 55 Point(double _x,double _y):x(_x),y(_y){} 56 void input(){ scanf("%lf%lf",&x,&y); } 57 void output(){ printf("%.2f %.2f\n",x,y); } 58 inline bool operator <(const Point &b)const{ 59 return (dcmp(x-b.x)==0? dcmp(y-b.y)<0 : x<b.x); 60 } 61 inline Point operator -(const Point &b)const{ 62 return Point(x-b.x,y-b.y); 63 } 64 inline double len2(){ //长度平方 65 return sqr(x)+sqr(y); 66 } 67 inline double len(){ //长度 68 return sqrt(len2()); 69 } 70 }; 71 72 inline double cross(Point a,Point b){ //叉积 73 return a.x*b.y-a.y*b.x; 74 } 75 76 inline double dot(Point a,Point b){ //点积 77 return a.x*b.x+a.y*b.y; 78 } 79 80 inline double dis(Point a,Point b){ //两点的距离 81 Point p=b-a; return p.len(); 82 } 83 84 struct Line{ 85 Point s,e; 86 Line(){} 87 Line(Point _s,Point _e):s(_s),e(_e){} //两点确定直线 88 void input(){ 89 s.input(); 90 e.input(); 91 } 92 double length(){ 93 return dis(s,e); 94 } 95 }; 96 97 inline double point_to_line(Point p,Line a){ //点到直线距离 98 return fabs(cross(p-a.s,a.e-a.s)/a.length()); 99 } 100 101 inline double point_to_seg(Point p,Line a){ //点到线段距离 102 if(dcmp(dot(p-a.s,a.e-a.s))<0||dcmp(dot(p-a.e,a.s-a.e))<0) 103 return min(dis(p,a.e),dis(p,a.s)); 104 return point_to_line(p,a); 105 } 106 107 inline double seg_to_seg(Line u,Line v){ 108 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)) ); 109 } 110 111 Line line[MAXN]; 112 113 bool cmp(Line a,Line b){ 114 return a.s<b.s; 115 } 116 117 int main(void){ 118 int T; scanf("%d",&T); 119 while(T--){ 120 int n; scanf("%d",&n); 121 for(int i=0;i<n;i++){ 122 line[i].input(); 123 if(line[i].e<line[i].s) swap(line[i].s,line[i].e); 124 } 125 sort(line,line+n,cmp); 126 double ans=1e10; 127 for(int i=0;i<n;i++) 128 for(int j=i+1;j<n;j++){ 129 if(dcmp(line[j].s.x-line[i].e.x-ans)>0) break; 130 ans=min(ans,seg_to_seg(line[i],line[j])); 131 } 132 printf("%.12f\n",ans); 133 } 134 return 0; 135 }