先在一个无穷高的位置画一条线为上界,把左右两端点向上连,形成一个封闭的多边形,求半平面交找到瞭望塔顶可以在的区域。因为点和点都是以直线连接的,斜率固定,所以半平面交到底边距离最近的点一定是某个拐点。那么把得到的集合内的线两两求一下交点,在从左到右依次求半平面交或是底边上的拐点到另一边的距离,找出最小值就可以了。
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=310;
struct node{
double x,y;
}p1[N],p2[N];
struct edge{
node s,t;
double x,y;
}l1[N];
struct edge2{
double x,y,k,b;
}l2[N];
double ans;
int n,l,r,q1[N],cnt,cnt2;
inline double cross(node a,node b,node c){
return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
}
bool cmp(edge i,edge j){
if(atan2(i.y,i.x)!=atan2(j.y,j.x))return atan2(i.y,i.x)<atan2(j.y,j.x);
return cross(i.s,i.t,j.t)<0;
}
bool cmp2(node i,node j){
return i.x<j.x;
}
inline bool rit(edge a,edge b,edge c){
node p;double k1,k2,b1,b2;
if(b.x==0)k2=c.y/c.x,b2=c.s.y-k2*c.s.x,p.x=b.s.x,p.y=p.x*k2+b2;
else if(c.x==0)k1=b.y/b.x,b1=b.s.y-k1*b.s.x,p.x=c.s.x,p.y=p.x*k1+b1;
else
k1=b.y/b.x,k2=c.y/c.x,b1=b.s.y-k1*b.s.x,b2=c.s.y-k2*c.s.x,
p.x=(b2-b1)/(k1-k2),p.y=p.x*k1+b1;
return cross(a.s,a.t,p)<0;
}
inline void getpt(edge b,edge c){
++cnt;double k1,k2,b1,b2;
if(b.x==0)k2=c.y/c.x,b2=c.s.y-k2*c.s.x,p2[cnt].x=b.s.x,p2[cnt].y=p2[cnt].x*k2+b2;
else if(c.x==0)k1=b.y/b.x,b1=b.s.y-k1*b.s.x,p2[cnt].x=c.s.x,p2[cnt].y=p2[cnt].x*k1+b1;
else
k1=b.y/b.x,k2=c.y/c.x,b1=b.s.y-k1*b.s.x,b2=c.s.y-k2*c.s.x,
p2[cnt].x=(b2-b1)/(k1-k2),p2[cnt].y=p2[cnt].x*k1+b1;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i)scanf("%lf",&p1[i].x);
for(int i=1;i<=n;++i)scanf("%lf",&p1[i].y);
for(int i=1;i<n;++i){
l1[i].s=p1[i],l1[i].t=p1[i+1],l1[i].x=p1[i+1].x-p1[i].x,l1[i].y=p1[i+1].y-p1[i].y;
l2[i].x=p1[i+1].x,l2[i].y=p1[i+1].y,l2[i].k=(l1[i].y/l1[i].x),l2[i].b=l2[i].y-l2[i].k*l2[i].x;
}
p1[n+1].x=p1[n].x,p1[n+1].y=1e16,p1[n+2].x=p1[1].x,p1[n+2].y=1e16;
l1[n].s=p1[n],l1[n].t=p1[n+1],l1[n].x=0,l1[n].y=p1[n+1].y-p1[n].y;
l1[n+1].s=p1[n+1],l1[n+1].t=p1[n+2],l1[n+1].x=p1[n+2].x-p1[n+1].x,l1[n+1].y=p1[n+2].y-p1[n+1].y;
l1[n+2].s=p1[n+2],l1[n+2].t=p1[1],l1[n+2].x=0,l1[n+2].y=p1[1].y-p1[n+2].y;
sort(l1+1,l1+n+3,cmp);
q1[1]=1,l=r=1;
for(int i=2;i<=n+2;++i){
if(atan2(l1[i].y,l1[i].x)==atan2(l1[i-1].y,l1[i-1].x))continue;
while(l<r&&rit(l1[i],l1[q1[r]],l1[q1[r-1]]))--r;
while(l<r&&rit(l1[i],l1[q1[l]],l1[q1[l+1]]))++l;
q1[++r]=i;
}
while(l<r&&rit(l1[q1[l]],l1[q1[r]],l1[q1[r-1]]))--r;
while(l<r&&rit(l1[q1[r]],l1[q1[l]],l1[q1[l+1]]))++l;
cnt=0;
for(int i=l;i<r;++i)getpt(l1[q1[i]],l1[q1[i+1]]);
if(l<r)getpt(l1[q1[l]],l1[q1[r]]);
sort(p2+1,p2+cnt+1,cmp2);
ans=1e16;cnt2=1;
while(l2[cnt2].x<=p2[1].x)++cnt2;
for(int i=1;i<=cnt;++i){
while(cnt2<n&&p2[i].x>=l2[cnt2].x)
ans=min(ans,(p2[i-1].y*(p2[i].x-l2[cnt2].x)+p2[i].y*(l2[cnt2].x-p2[i-1].x))/(p2[i].x-p2[i-1].x)-l2[cnt2].y),++cnt2;
ans=min(ans,p2[i].y-(p2[i].x*l2[cnt2].k+l2[cnt2].b));
}
printf("%.3lf",ans);
return 0;
}