• poj3525 Most Distant Point from the Sea


    题目描述:

    vjudge

    POJ

    题解:

    二分答案+半平面交。

    半径范围在0到5000之间二分,每次取$mid$然后平移所有直线,判断半平面交面积是否为零。

    我的eps值取的是$10^{-12}$,36ms,而且和样例一样。

    (大力推荐)

    代码:

    #include<cmath>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N = 150;
    const double eps = 1e-12;
    int dcmp(double x)
    {
        if(fabs(x)<=eps)return 0;
        return x>0?1:-1;
    }
    struct Point
    {
        double x,y;
        Point(){}
        Point(double x,double y):x(x),y(y){}
        Point operator + (const Point&a)const{return Point(x+a.x,y+a.y);}
        Point operator - (const Point&a)const{return Point(x-a.x,y-a.y);}
        Point operator * (const double&a)const{return Point(x*a,y*a);}
        Point operator / (const double&a)const{return Point(x/a,y/a);}
        double operator * (const Point&a)const{return x*a.x+y*a.y;}
        double operator ^ (const Point&a)const{return x*a.y-y*a.x;}
    };
    typedef Point Vector;
    typedef vector<Point> Pol;
    double ang(const Vector&a){return atan2(a.x,a.y);}
    double lth(const Vector&a){return sqrt(a*a);}
    Vector Vil(const Vector&a){return Vector(-a.y,a.x)/lth(a);}
    struct Line
    {
        Point p;
        Vector v;
        Line(){}
        Line(Point p,Vector v):p(p),v(v){}
        Line operator + (const Vector&a)const{return Line(p+a,v);}
        bool operator < (const Line&a)const{return ang(v)<ang(a.v);}
    };
    int n;
    Point p[N],tp[N];
    Vector vp[N];
    Line s0[N],s[N],ts[N];
    bool Onleft(Line l,Point p)
    {
        return dcmp(l.v^(p-l.p))>0;
    }
    Point L_L(Line a,Line b)
    {
        double t = ((b.p-a.p)^(b.v))/(a.v^b.v);
        return a.p+a.v*t;
    }
    double S_(Pol&P)
    {
        double ans = 0.0;
        for(int i=1,lim=(int)P.size();i<lim;i++)
            ans+=((P[i-1]-P[0])^(P[i]-P[0]));
        return fabs(ans)/2;
    }
    double bpmj()
    {
        int hd,tl;
        ts[hd=tl=0]=s[1];
        for(int i=2;i<=n;i++)
        {
            while(hd<tl&&!Onleft(s[i],tp[tl-1]))tl--;
            while(hd<tl&&!Onleft(s[i],tp[hd]))hd++;
            ts[++tl] = s[i];
            if(!dcmp(s[i].v^ts[tl-1].v))
            {
                tl--;
                if(Onleft(ts[tl],s[i].p))ts[tl]=s[i];
            }
            tp[tl-1]=L_L(ts[tl-1],ts[tl]);
        }
        while(hd<tl&&!Onleft(ts[hd],tp[tl-1]))tl--;
        if(tl-hd<=1)return 0;
        tp[tl]=L_L(ts[hd],ts[tl]);
        Pol P;
        for(int i=hd;i<=tl;i++)P.push_back(tp[i]);
        return S_(P);
    }
    bool check(double mid)
    {
        for(int i=1;i<=n;i++)s[i]=s0[i]+vp[i]*mid;
        return dcmp(bpmj())>0;
    }
    int main()
    {
        while(scanf("%d",&n)&&n!=0)
        {
            for(int i=1;i<=n;i++)scanf("%lf%lf",&p[i].x,&p[i].y);
            for(int i=1;i<n;i++)s0[i]=Line(p[i],p[i+1]-p[i]);
            s0[n]=Line(p[n],p[1]-p[n]);
            sort(s0+1,s0+1+n);
            for(int i=1;i<=n;i++)    
                vp[i]=Vil(s0[i].v);
            double l = 0.0,r = 5000.0;
            while(dcmp(r-l))
            {
                double mid = (l+r)/2;
                if(check(mid))l=mid;
                else r=mid;
            }
            printf("%lf
    ",r);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    _I、_O、_IO的含义
    ARM启动代码中_main 与用户主程序main()的区别
    ARM汇编程序中的伪指令
    oracle密码过期问题
    等待界面-调转页面前button篇
    等待效果
    winfrom中Application.Restart()
    自动刷新处理
    泛微E8二次开发
    我的菜园子
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10994536.html
Copyright © 2020-2023  润新知