POJ 3525 Most Distant Point from the Sea(半平面交)

题目链接:http://poj.org/problem?id=3525

题意:多边形内一个圆。该圆的最大半径是多少?

思路:二分半径r。将每条边向内移动r的距离。若得到的还是多边形则说明r可以。





int DB(double x)

{

    if(x>1e-10) return 1;

    if(x<-1e-10) return -1;

    return 0;

}



struct point

{

    double x,y;



    point(){}

    point(double _x,double _y)

    {

        x=_x;

        y=_y;

    }



    void read()

    {

        RD(x,y);

    }



    void output()

    {

        printf("(%.2lf %.2lf)",x,y);

    }



    point operator+(point a)

    {

        return point(x+a.x,y+a.y);

    }

    point operator-(point a)

    {

        return point(x-a.x,y-a.y);

    }



    double operator*(point a)

    {

        return x*a.y-y*a.x;

    }



    point operator*(double t)

    {

        return point(x*t,y*t);

    }



    point operator/(double t)

    {

        return point(x/t,y/t);

    }



    bool operator==(point a)

    {

        return DB(x-a.x)==0&&DB(y-a.y)==0;

    }



    bool operator!=(point a)

    {

        return DB(x-a.x)||DB(y-a.y);

    }

};



point a[N],b[N];

int n;





//t在ab的左侧返回正值

double cross(point a,point b,point t)

{

    return point(b-a)*point(t-a);

}





point getCross(point a,point b,point p,point q)

{

    double s1=(a-p)*(b-p);

    double s2=(b-q)*(a-q);

    double t=s1+s2;

    return (p*s2+q*s1)/(s1+s2);

}



double getDist(point a,point b)

{

    return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));

}



void moveSegment(point &p1,point &p2,double r)

{

    r/=getDist(p1,p2);

    point p=point(p1.y-p2.y,p2.x-p1.x)*r;

    p1=p1+p;

    p2=p2+p;

}



void cut(point a[],int &n,point p1,point p2)

{

    point b[N],p;

    int i,m=n,t1,t2;

    FOR0(i,n) b[i]=a[i];

    b[n]=b[0];

    n=0;

    FOR0(i,m)

    {

        t1=DB(cross(p1,p2,b[i]));

        t2=DB(cross(p1,p2,b[i+1]));

        if(!t1||!t2)

        {

            if(!t1) a[n++]=b[i];

            if(!t2) a[n++]=b[i+1];

        }

        else if(t1>0&&t2>0) a[n++]=b[i],a[n++]=b[i+1];

        else if(t1*t2==-1)

        {

            p=getCross(p1,p2,b[i],b[i+1]);

            if(t1>0) a[n++]=b[i],a[n++]=p;

            else a[n++]=p,a[n++]=b[i+1];

        }

    }

    if(!n) return;

    m=1;

    FOR1(i,n-1) if(a[i]!=a[i-1]) a[m++]=a[i];

    if(a[m-1]==a[0]) m--;

    n=m;

}



double getRadius(point a[],int n)

{

    double low=0,high=1e10,mid;

    point p1,p2,b[N];

    int i,m;



    a[n]=a[0];

    while(high-low>1e-10)

    {

        mid=(low+high)/2;

        m=n;

        FOR0(i,n) b[i]=a[i];

        FOR0(i,n)

        {

            p1=a[i];p2=a[i+1];

            moveSegment(p1,p2,mid);

            cut(b,m,p1,p2);

        }

        if(m>0) low=mid+1e-10;

        else high=mid-1e-10;

    }

    return mid;

}







int main()

{

    while(scanf("%d",&n),n)

    {

        int i;

        FOR0(i,n) a[i].read();

        double r=getRadius(a,n);

        printf("%.6lf\n",r);

    }

    return 0;

}

  

你可能感兴趣的:(ant)