POJ 3525 Most Distant Point from the Sea

来源:互联网 发布:js为二维数组赋值 编辑:程序博客网 时间:2024/06/11 20:51

题意 :给你一个小岛,是一个凸多边形,问你这个多边形的内部的点到所有边的最小值最大。

题解 :对于最小值最大的问题,不难想到要用二分去做,不难发现这个题的距离是满足二分性质的,然后将每天边向内部缩 dist 怎么缩呢 ? (通过一天边旋转90 度 就可以了) 。由于这个题给你的是一个凸多边形所以剩下的就可以用半平面交解决了,如果半平面交存在,那么这个答案检验就是可以的。

emmm……. 剩下的就是半平面交的模版了。

#include <algorithm>#include <iostream>#include <cstring>#include <cstdio>#include <cmath>#define PI 3.1415926using namespace std;#define N 1005const double eps=1e-8;int dcmp(double x) {    if (x<=eps&&x>=-eps) return 0;    return (x>0)?1:-1;}struct Vector {    double x,y;    Vector(double X=0,double Y=0){        x=X,y=Y;    }};typedef Vector Point;struct Line {    Point p;    Vector v;    double ang;    Line(Point P=Point(0,0),Vector V=Vector(0,0)) {        p=P,v=V;        ang=atan2(v.y,v.x);    }    bool operator < (const Line &a) const {        return ang<a.ang;    }};Vector operator + (Vector a,Vector b) {return Vector(a.x+b.x,a.y+b.y);}Vector operator - (Vector a,Vector b) {return Vector(a.x-b.x,a.y-b.y);}Vector operator * (Vector a,double b) {return Vector(a.x*b,a.y*b);}int n,l,r,cnt;double ans;Line L[N],q[N];Point p[N],poly[N];double Cross(Vector a,Vector b) {    return a.x*b.y-a.y*b.x;}Point GLI(Point P,Vector v,Point Q,Vector w) {    Vector u=P-Q;    double t=Cross(w,u)/Cross(v,w);    return P+v*t;}bool Onleft(Line m,Point P) {    Vector w=P-m.p;    return dcmp(Cross(m.v,w))>=0;}void halfp(){    sort(L+1,L+n+1);    cnt=0;    q[l=r=1]=L[1];    for (int i=2;i<=n;++i) {        while (l<r&&!Onleft(L[i],p[r-1])) --r;        while (l<r&&!Onleft(L[i],p[l])) ++l;        q[++r]=L[i];        if (dcmp(Cross(q[r].v,q[r-1].v))==0) {            --r;            if (Onleft(q[r],L[i].p))                q[r]=L[i];        }        if (l<r)            p[r-1]=GLI(q[r-1].p,q[r-1].v,q[r].p,q[r].v);    }    while (l<r&&!Onleft(q[l],p[r-1]))        --r;    if (r-l<=1) return;    p[r]=GLI(q[r].p,q[r].v,q[l].p,q[l].v);    for (int i=l;i<=r;++i) poly[++cnt]=p[i];}double Area() {    double ans=0;    for (int i=2;i<cnt;++i)        ans+=Cross(poly[i]-poly[1],poly[i+1]-poly[1]);    return fabs(ans/2);}int main() {    while(scanf("%d",&n) && n) { // 输入点的个数    Point temp[N],temp0,temp1;    Point pp[N];    Line LL[N];    double ang[N];    for (int i=1;i<=n;++i) {        double x,y;        scanf ("%lf%lf",&x,&y);        pp[i] = Point (x,y);        temp[i] = pp[i];    } // 开始需要设置一个无限大的区域    pp[n + 1] = pp[1];    temp[n + 1] = pp[1];    for (int i = 1;i <= n; ++ i) {        L[i] = Line(pp[i],pp[i + 1] - pp[i]);        LL[i] = L[i];        ang[i] = L[i].ang;    }//    for (int i = 1;i <= n; ++ i) printf("%d  %.6f\n",i,LL[i].ang);    L[++n] = Line(Point(0,10000),Vector(0,-10000));    L[++n] = Line(Point(0,0),Vector(10000,0));    L[++n] = Line(Point(10000,0),Vector(0,10000));    L[++n] = Line(Point(10000,10000),Vector(-10000,0));    double R = 10000.0,Ll = 0.0;    double mid = (R + Ll) / 2;//    halfp();//    printf("%.6f\n",Area());//    cout << cnt << endl;//    for (int i = 1;i <= n - 4; ++ i) printf("%d  %.6f\n",i,LL[i].ang);    while (R - Ll > eps) {        mid = (R + Ll) / 2.0;;        for (int i = 1;i <= n - 4; ++ i) {            double angd = ang[i] + PI / 2.0;            double addx = mid * cos (angd);            double addy = mid * sin (angd);            temp0 = temp[i];            temp1 = temp[i + 1];            temp0.x += addx,temp0.y += addy;            temp1.x += addx,temp1.y += addy;            L[i] = Line (temp0,temp1 - temp0);        //   printf("%.3f %.3f %.3f\n",mid,L[i].p.x,L[i].p.y);        }        L[n] = Line(Point(0,10000),Vector(0,-10000));        L[n - 1] = Line(Point(0,0),Vector(10000,0));        L[n - 2] = Line(Point(10000,0),Vector(0,10000));        L[n - 3] = Line(Point(10000,10000),Vector(-10000,0));        halfp();        if (cnt >= 1) Ll = mid;        else R = mid;//        printf ("%.6f\n",mid);    }    printf ("%.6f\n",mid);    }    return 0;}/* 3 0.000 312.500 9901.179 -296.464 7044.194 690.641 */