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 }
posted @ 2019-08-21 22:54  DD_BOND  阅读(586)  评论(0编辑  收藏  举报