【题意分析】
求一个下凸壳与一段折线的距离。
【解题思路】
先把直线按斜率排序,求出下凸壳,然后枚举所有的顶点的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 ",ans),0; 140 }