【题意分析】

  求一个下凸壳与一段折线的距离。

【解题思路】

  先把直线按斜率排序,求出下凸壳,然后枚举所有的顶点的x坐标求最短y坐标差,复杂度O(nlog2n)。

【参考代码】

  1 #include <algorithm>
  2 #include <cstdio>
  3 #define REP(i,low,high) for(register int i=(low);i<=(high);++i)
  4 #define __function__(type) /*__attribute__((optimize("-O2"))) inline */type
  5 #define __procedure__ /*__attribute__((optimize("-O2"))) inline */void
  6 using namespace std;
  7  
  8 //defs {
  9 #include <cmath>
 10 template<typename real>
 11 inline __function__(bool) fequals(
 12     const real&one,const real&another,const real&eps=1e-6
 13 ) {return fabs(one-another)<eps;}
 14 template<typename real>
 15 inline __function__(bool) funequals(
 16     const real&one,const real&another,const real&eps=1e-6
 17 ) {return fabs(one-another)>=eps;}
 18 //} defs
 19  
 20 //geometry {
 21 template<typename T=double> struct Point
 22 {
 23     T x,y; Point(const T&_x=0,const T&_y=0):x(_x),y(_y) {}
 24     __function__(bool) operator==(const Point<T>&thr)const
 25     {
 26         return fequals(x,thr.x)&&fequals(y,thr.y);
 27     }
 28     __function__(bool) operator!=(const Point<T>&thr)const
 29     {
 30         return funequals(x,thr.x)||funequals(y,thr.y);
 31     }
 32     __function__(Point<T>) operator+(const Point<T>&thr)const
 33     {
 34         return Point<T>(x+thr.x,y+thr.y);
 35     }
 36     __function__(Point<T>) operator-(const Point<T>&thr)const
 37     {
 38         return Point<T>(x-thr.x,y-thr.y);
 39     }
 40     __function__(Point<T>) operator*(const T&lambda)const
 41     {
 42         return Point<T>(x*lambda,y*lambda);
 43     }
 44     __function__(Point<double>) operator/(const T&lambda)const
 45     {
 46         return Point<double>(double(x)/lambda,double(y)/lambda);
 47     }
 48     __function__(double) theta()const
 49     {
 50         return x>0?(y<0)*2*M_PI+atan(y/x):M_PI+atan(y/x);
 51     }
 52     __function__(double) theta_x()const{return x?atan(y/x):M_PI/2;}
 53     __function__(double) theta_y()const{return y?atan(x/y):M_PI/2;}
 54 };
 55 template<typename T>
 56 inline __function__(T) dot_product(const Point<T>&A,const Point<T>&B)
 57 {
 58     return A.x*B.x+A.y*B.y;
 59 }
 60 template<typename T>
 61 inline __function__(T) cross_product(const Point<T>&A,const Point<T>&B)
 62 {
 63     return A.x*B.y-A.y*B.x;
 64 }
 65 template<typename T>
 66 inline __function__(double) Euclid_distance(const Point<T>&A,const Point<T>&B)
 67 {
 68     return sqrt(pow(A.x-B.x,2),pow(A.y-B.y,2));
 69 }
 70 template<typename T>
 71 inline __function__(T) Manhattan_distance(const Point<T>&A,const Point<T>&B)
 72 {
 73     return fabs(A.x-B.x)+fabs(A.y-B.y);
 74 }
 75 struct kbLine
 76 {
 77     //line:y=kx+b
 78     double k,b; kbLine(const double&_k=0,const double&_b=0):k(_k),b(_b) {}
 79     __function__(bool) operator==(const kbLine&thr)const
 80     {
 81         return fequals(k,thr.k)&&fequals(b,thr.b);
 82     }
 83     __function__(bool) operator!=(const kbLine&thr)const
 84     {
 85         return funequals(k,thr.k)||funequals(b,thr.b);
 86     }
 87     __function__(bool) operator<(const kbLine&thr)const{return k<thr.k;}
 88     __function__(bool) operator>(const kbLine&thr)const{return k>thr.k;}
 89     template<typename T>
 90     __function__(bool) build_line(const Point<T>&A,const Point<T>&B)
 91     {
 92         return fequals(A.x,B.x)?0:(k=double(A.y-B.y)/(A.x-B.x),b=A.y-k*A.x,1);
 93     }
 94     __function__(double) theta_x()const{return atan(k);}
 95     __function__(double) theta_y()const{return theta_x()-M_PI/2;}
 96     __function__(double) get(const double&x)const{return k*x+b;}
 97 };
 98 __function__(bool) parallel(const kbLine&A,const kbLine&B)
 99 {
100     return A!=B&&(fequals(A.k,B.k)||A.k!=A.k&&B.k!=B.k);
101 }
102 __function__(Point<double>*) cross(const kbLine&A,const kbLine&B)
103 {
104     if(A==B||parallel(A,B)) return NULL; double _x=double(B.b-A.b)/(A.k-B.k);
105     Point<double>*ret=new Point<double>(_x,A.k*_x+A.b); return ret;
106 }
107 //} geometry
108  
109 static int n; double x[310],y[310]; int stack[310]; kbLine L[310];
110  
111 int main()
112 {
113     scanf("%d",&n); REP(i,1,n) scanf("%lf",x+i); REP(i,1,n) scanf("%lf",y+i);
114     REP(i,1,n-1) L[i].build_line(Point<>(x[i],y[i]),Point<>(x[i+1],y[i+1]));
115     sort(L+1,L+n); int top=stack[1]=1; REP(i,2,n-1)
116     {
117         for(;i<=n&&(L[i]==L[stack[top]]||parallel(L[i],L[stack[top]]));++i);
118         for(;i<=n&&top>1;--top)
119         {
120             Point<>*last=cross(L[stack[top-1]],L[stack[top]]),
121                    * now=cross(L[     i      ],L[stack[top]]);
122             if(last->x<now->x) break; delete last; delete now;
123         }
124         stack[++top]=i;
125     }
126     double ans=1e10; int j=2;
127     REP(i,1,n)
128     {
129         for(;L[stack[j]].get(x[i])>L[stack[j-1]].get(x[i]);++j);
130         ans=min(ans,L[stack[--j]].get(x[i])-y[i]);
131     }
132     REP(i,2,top)
133     {
134         Point<>*now=cross(L[stack[i-1]],L[stack[i]]);
135         j=upper_bound(x+1,x+n+1,now->x)-x; kbLine tmp;
136         tmp.build_line(Point<>(x[j-1],y[j-1]),Point<>(x[j],y[j]));
137         ans=min(ans,now->y-tmp.get(now->x)); delete now;
138     }
139     return printf("%.3lf\n",ans),0;
140 }
View Code