学习了半平交面。
我这里写的是训练指南中的双端队列,每次判断是否删去更优然后更新。
看hzwer中有一处不太明白就是为何要将两段加入队列
后来对拍出错才知道是因为精度,当两线重合时他们叉积返回值是一个极小值
所以判断一下精度即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=2005; 4 int n,m,cnt,tot;double ans=1e20,eps=1e-8; 5 struct point{ 6 double x,y; 7 }a[N],p[N]; 8 point operator -(point a,point b){ 9 point t;t.x=b.x-a.x;t.y=b.y-a.y; 10 return t; 11 } 12 double operator *(point a,point b){ 13 return a.x*b.y-a.y*b.x; 14 } 15 struct line{ 16 point a,b;double slop; 17 bool operator <(const line &B)const{ 18 return slop==B.slop?(b-a)*(B.b-a)>0:slop<B.slop; 19 } 20 }l[N],s[N]; 21 point inter(line a,line b){ 22 double k1,k2,t; 23 k1=(b.b-a.a)*(a.b-a.a); 24 k2=(a.b-a.a)*(b.a-a.a); 25 t=k1/(k1+k2); 26 point ans; 27 ans.x=b.b.x+(b.a.x-b.b.x)*t; 28 ans.y=b.b.y+(b.a.y-b.b.y)*t; 29 return ans; 30 } 31 bool jud(line a,line b,line t) 32 { 33 point pp=inter(a,b); 34 return (t.b-t.a)*(pp-t.a)<-eps; 35 } 36 void hpl() 37 { 38 int L=1,R=0; 39 for(int i=1;i<=cnt;++i) 40 { 41 if(l[i].slop!=l[i-1].slop)++tot; 42 l[tot]=l[i]; 43 } 44 cnt=tot;tot=0; 45 s[++R]=l[1];s[++R]=l[2]; 46 for(int i=3;i<=cnt;++i) 47 { 48 while(L<R&&jud(s[R-1],s[R],l[i]))R--; 49 while(L<R&&jud(s[L+1],s[L],l[i]))L++; 50 s[++R]=l[i]; 51 } 52 while(L<R&&jud(s[R-1],s[R],s[L]))R--; 53 54 while(L<R&&jud(s[L+1],s[L],s[R]))L++; 55 for(int i=L;i<R;++i) 56 a[++tot]=inter(s[i],s[i+1]); 57 } 58 void getans() 59 { 60 for(int i=1;i<=tot;++i) 61 { 62 point t;t.x=a[i].x;t.y=-1; 63 for(int j=1;j<n;++j) 64 if(p[j].x<=a[i].x&&p[j+1].x>=a[i].x) 65 ans=min(ans,a[i].y-inter((line){p[j],p[j+1]},(line){t,a[i]}).y); 66 } 67 for(int i=1;i<=n;++i) 68 { 69 point t;t.x=p[i].x;t.y=-1; 70 for(int j=1;j<tot;++j) 71 if(a[j].x<=p[i].x&&a[j+1].x>=p[i].x) 72 ans=min(ans,inter((line){a[j],a[j+1]},(line){t,p[i]}).y-p[i].y); 73 } 74 } 75 int main() 76 { 77 // freopen("1.out","r",stdin); 78 // freopen("my.out","w",stdout); 79 scanf("%d",&n); 80 for(int i=1;i<=n;++i)scanf("%lf",&p[i].x); 81 for(int i=1;i<=n;++i)scanf("%lf",&p[i].y); 82 // p[0].x=p[1].x;p[0].y=1e9; 83 // p[n+1].x=p[n].x;p[n+1].y=1e9; 84 for(int i=1;i<n;++i)l[++cnt].a=p[i],l[cnt].b=p[i+1]; 85 if(cnt<3){ 86 puts("0.000");return 0; 87 } 88 for(int i=1;i<=cnt;++i) 89 l[i].slop=atan2(l[i].b.y-l[i].a.y,l[i].b.x-l[i].a.x); 90 sort(l+1,l+1+cnt); 91 hpl(); 92 getans(); 93 printf("%.3lf",ans); 94 return 0; 95 }