bzoj1038 瞭望塔【半平面交】

来源:互联网 发布:福彩3d算法 编辑:程序博客网 时间:2024/05/21 09:28

解题思路:

可以发现,可以看到所有区域的点都位于轮廓线的上半平面交内,如样例:

这里写图片描述

yy一下,发现最优修建地点就在轮廓线或半平面交的转折点的垂线与另一条的交点所组成的线段,由于是交错递增的,可以O(n)处理出。

这道题求半平面交时可以只用栈,因为后面的直线不可能与最前面的相交。

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<ctime>#include<queue>#include<vector>#include<set>using namespace std;int getint(){    int i=0,f=1;char c;    for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());    if(c=='-')c=getchar(),f=-1;    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';    return i*f;}const int N=305;const double eps=1e-8,INF=1e18;struct point{    double x,y;    point(){}    point(double _x,double _y):        x(_x),y(_y){}    inline friend point operator + (const point &a,const point &b)    {return point(a.x+b.x,a.y+b.y);}    inline friend point operator - (const point &a,const point &b)    {return point(a.x-b.x,a.y-b.y);}    inline friend point operator * (const point &a,double b)    {return point(a.x*b,a.y*b);}    inline friend point operator / (const point &a,double b)    {return point(a.x/b,a.y/b);}    inline friend double operator * (point a,point b)    {return a.x*b.y-a.y*b.x;}}p[N],q[N];struct line{    point st,ed;    double ang;    line(){}    line(point _st,point _ed):st(_st),ed(_ed)    {ang=(ed-st).y*1.0/(ed-st).x;}    inline friend bool operator < (const line &a,const line &b)    {        if(abs(a.ang-b.ang)<eps)return (a.ed-a.st)*(b.ed-a.st)>0;        return a.ang<b.ang;    }}sta[N],l[N];int n,m,top,tot;point getcross(line a,line b){    double x=(a.ed-a.st)*(b.st-a.st);    double y=(b.ed-a.st)*(a.ed-a.st);    point t=b.st+(b.ed-b.st)*x/(x+y);    return t;}bool right(point a,line b){    return (b.ed-a)*(b.st-a)>=0;}void HPI(){    sort(l+1,l+n);    l[++tot]=l[1];    for(int i=2;i<n;i++)    {        if(abs(l[i].ang-l[i-1].ang)>eps)tot++;        l[tot]=l[i];    }    sta[++top]=l[1],sta[++top]=l[2];    for(int i=3;i<=tot;i++)    {        while(top>1&&right(getcross(sta[top],sta[top-1]),l[i]))top--;        sta[++top]=l[i];    }    for(int i=1;i<top;i++)        q[++m]=getcross(sta[i],sta[i+1]);    q[++m]=point(INF,0);}void solve(){    double ans=INF;    int i=1,j=1;    while(i<=n&&j<=m)    {        if(p[i].x<q[j].x)        {            point t=getcross(sta[j],line(p[i],point(p[i].x,INF)));            ans=min(ans,abs(t.y-p[i].y));            i++;        }        else         {            point t=getcross(line(p[i],p[i-1]),line(q[j],point(q[j].x,INF)));            ans=min(ans,abs(t.y-q[j].y));            j++;        }    }    printf("%0.3f",ans);}int main(){    //freopen("lx.in","r",stdin);    n=getint();    for(int i=1;i<=n;i++)p[i].x=getint();    for(int i=1;i<=n;i++)p[i].y=getint();    for(int i=1;i<n;i++)        l[i]=line(p[i],p[i+1]);    HPI();    solve();    return 0;}