【题目网址】
http://www.lydsy.com/JudgeOnline/problem.php?id=1038
【我的题解】
半平面交,学了三天aaaaaaa
一开始只有一本ACM教程,那上面根本说的不全(预处理只字未提),后来多亏了hzwer的悉心解答,才搞懂了
关于半平面交我可能在以后写个总结
这道题就是先半平面交,求出一个凸包,对于凸包上的每个点,做一条平行于y轴的直线,交下面的轮廓于一个点,用这个点和你枚举的点的距离更新ans。对于轮廓的折点,也做同样的处理,用距离更新ans。(具体为什么画个图就知道了)
【我的代码】
//半平面交
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#define maxn 400
#define inf 1e10
using namespace std;
int N, cnt;
struct point{double x,y;}p[maxn], sur[maxn];
struct vec
{
point a, b;
double k;
double operator*(vec v)
{
double x1=b.x-a.x, x2=v.b.x-v.a.x, y1=b.y-a.y, y2=v.b.y-v.a.y;
return x1*y2-x2*y1;
}
}q[maxn], seg[maxn];
void init()
{
int i;
scanf("%d",&N);
for(i=1;i<=N;i++)scanf("%lf",&p[i].x);
for(i=1;i<=N;i++)scanf("%lf",&p[i].y);
for(i=1;i<N;i++)seg[i]=(vec){p[i],p[i+1]};
seg[N]=(vec){(point){-inf,inf},(point){-inf,-inf}};
seg[N+1]=(vec){(point){-inf,-inf},(point){inf,-inf}};
seg[N+2]=(vec){(point){inf,-inf},(point){inf,inf}};
seg[N+3]=(vec){(point){inf,inf},(point){-inf,inf}};
cnt=N+3;
for(i=1;i<=cnt;i++)
seg[i].k=atan2((seg[i].b.y-seg[i].a.y),(seg[i].b.x-seg[i].a.x));
}
bool in(point p, vec v)
{
vec vv=(vec){v.a,p};
return vv*v<0;
}
bool cmp(vec v1, vec v2)
{return v1.k==v2.k?in(v1.a,v2):v1.k<v2.k;}
point cross(vec v1, vec v2)
{
double k1, k2, b1, b2, x, y;
k1=(v1.a.y-v1.b.y)/(v1.a.x-v1.b.x);
k2=(v2.a.y-v2.b.y)/(v2.a.x-v2.b.x);
b1=-k1*v1.a.x+v1.a.y;
b2=-k2*v2.a.x+v2.a.y;
if(v1.a.x==v1.b.x)x=v1.a.x, y=k2*x+b2;
else if(v2.a.x==v2.b.x)x=v2.a.x, y=k1*x+b1;
else x=(b1-b2)/(k2-k1), y=k1*x+b1;
return (point){x,y};
}
void work()
{
int i, l, r, x;
sort(seg+1,seg+cnt+1,cmp);
for(i=2,x=1;i<=cnt;i++)if(seg[i].k!=seg[i-1].k)seg[++x]=seg[i];
cnt=x;
q[l=1]=seg[1];
q[r=2]=seg[2];
for(i=3;i<=cnt;i++)
{
while(l<r and !in(cross(q[r],q[r-1]),seg[i]))r--;
while(l<r and !in(cross(q[l],q[l+1]),seg[i]))l++;
q[++r]=seg[i];
}
while(l<r and !in(cross(q[r],q[r-1]),q[l]))r--;
while(l<r and !in(cross(q[l],q[l+1]),q[r]))l++;
cnt=0;
for(i=l;i<r;i++)sur[++cnt]=cross(q[i],q[i+1]);
sur[0]=cross(q[r],q[l]);
}
void getans()
{
int i, j;
double ans=inf;
point t;
for(i=1;i<cnt;i++)
for(j=1;j<N;j++)
if(sur[i].x>=p[j].x and sur[i].x<=p[j+1].x)
{
t=cross((vec){sur[i],(point){sur[i].x,inf}},(vec){p[j],p[j+1]});
ans=min(ans,sur[i].y-t.y);
}
for(i=1;i<=N;i++)
for(j=0;j<cnt;j++)
if(p[i].x>=sur[j].x and p[i].x<=sur[j+1].x)
{
t=cross((vec){p[i],(point){p[i].x,inf}},(vec){sur[j],sur[j+1]});
ans=min(ans,t.y-p[i].y);
}
printf("%.3lf\n",ans);
}
int main()
{
init();
work();
getans();
return 0;
}