• POJ


    题目链接:https://vjudge.net/problem/POJ-3525

    题意:求半平面交内的最大圆半径。

    思路:二分半径,每次让所有的边推进mid,然后再跑半平面交,看是否有解,然后再不断更新即可。然后就只剩下考虑如何将每条边推进R了。

    可以把直线表示成Ax + By + C = 0后,把直线向内推进d时,只需要写:C=C+R*sqrt(A*A+B*B)。此时的Ax + By + C = 0就是推进R后的函数了。

    在vj上用G++交一直答案错误,用C++交就过了。又是这样。。。。。。。。

    用C++交重载减号编译过不了,要重新写个函数改下代码才能过。。。。。。。。

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    const int maxn = 1e4;
    const double EPS = 1e-7;
    struct point//
    {
        double x,y;
        point friend operator -(point A,point B)
        {
            return {A.x-B.x,A.y-B.y};
        }
    };
    struct line//线
    {
        point x,y;
    };
    point p[maxn],q[maxn];
    line L[maxn],que[maxn],R[maxn];
    double chaj(point A,point B)//差积
    {
        return A.x*B.y-A.y*B.x;
    }
    bool fanx(int N)//判断是否为逆序
    {
        double sum=0;
        for(int i=2; i<N; i++)
            sum+=chaj(p[i]-p[1],p[i+1]-p[1]);
        return sum<0;//正序
    }
    double getAngle(point A)//获得极角角度
    {
        return atan2(A.y,A.x);
    }
    bool cmp(line A,line B)//根据极角排序,极角相同,左边的排到前面
    {
        double sum1=getAngle(A.y-A.x);
        double sum2=getAngle(B.y-B.x);
        if (fabs(sum1 - sum2) < EPS)
            return chaj(A.y-A.x,B.y-A.x)<=0;
        return sum1<sum2;
    }
    point getIntersectPoint(line A, line B)//得到两条线的交点
    {
        double a1 = A.x.y - A.y.y, b1 = A.y.x - A.x.x, c1 = A.x.x * A.y.y - A.y.x * A.x.y;
        double a2 = B.x.y - B.y.y, b2 = B.y.x - B.x.x, c2 = B.x.x * B.y.y - B.y.x * B.x.y;
        point PO;
        PO.x= (c1*b2-c2*b1)/(a2*b1-a1*b2);
        PO.y= (a2*c1-a1*c2)/(a1*b2-a2*b1);
        return PO;
    }
    line getLine(line Q,double R)//直线向左平移R,Ax+By+C=0
    {
        double A=Q.y.y-Q.x.y;
        double B=Q.x.x-Q.y.x;
        double C=Q.x.y*Q.y.x-Q.y.y*Q.x.x;
        C=C+R*sqrt(A*A+B*B);
        line P;
        if(fabs(Q.x.x-Q.y.x)>0)//线不是竖直的
        {
            P.x.x=Q.x.x;
            P.x.y=-(A*Q.x.x+C)/B;
            P.y.x=Q.y.x;
            P.y.y=-(A*Q.y.x+C)/B;
        }
        else
        {
            P.x.y=Q.x.y;
            P.x.x=-(B*Q.x.y+C)/A;
            P.y.y=Q.y.y;
            P.y.x=-(B*Q.y.y+C)/A;
        }
        return P;
    }
    bool onRight(line A, line B, line C)//判断 b,c 的交点是否在 a 的右边
    {
        point o = getIntersectPoint(B, C);
        if( chaj( A.y - A.x,o - A.x )<0 )
            return true;
        return false;
    }
    bool HalfPlaneIntersection(int cnt)
    {
        int head=0,tail=0;
        for(int i=1; i<=cnt; i++)
        {
            //判断新加入直线产生的影响
            while(tail-head>1 && onRight(L[i], que[tail - 1], que[tail - 2]))
                tail--;
            while(tail-head>1 && onRight(L[i], que[head], que[head + 1]))
                head++;
            que[tail++]=L[i];
        }
        //最后判断最先加入的直线和最后的直线的影响
        while(tail-head>1 && onRight(que[head], que[tail-1], que[tail-2]))
            tail--;
        while(tail-head>1 && onRight(que[tail-1], que[head], que[head+1]))
            head++;
        //半平面交存在que中, head到tail-1
        if (tail-head >= 3)
            return true;
        return false;
    }
    int main()
    {
        int N;
        while(~scanf("%d",&N))
        {
            if(N==0)
                break;
            for(int i=1; i<=N; i++)
                cin>>p[i].x>>p[i].y;
            for(int i=1; i<N; i++)
            {
                R[i].x=p[i];
                R[i].y=p[i+1];
            }
            R[N].x=p[N];
            R[N].y=p[1];
            sort(R+1,R+N+1,cmp);
            int cnt=1;//去重后的个数
            for(int i=2; i<=N; i++)
            {
                if (fabs(getAngle(R[i].y-R[i].x) - getAngle(R[i-1].y-R[i-1].x)) < EPS)
                    continue;
                R[++cnt]=R[i];
            }
            double l=0,r=10000000;//二分左右
            while(r-l>EPS)
            {
                double mid=(l+r)/2.0;
                for(int i=1;i<=cnt;i++)
                    L[i]=getLine(R[i],mid);
                if(HalfPlaneIntersection(cnt))
                    l=mid;
                else
                    r=mid;
            }
            printf("%.6lf
    ",r);
        }
    }
  • 相关阅读:
    C# OCR 文字识别[初级]
    首次试用 NeoSwiff ,用C#开发FLASH版的多国语言翻译
    星期天上午买了个nokia 的NGage QD手机
    高兴,今天总算鸟枪换炮了~
    3年前的小程序:破解需要delphi IDE 环境的vcl 控件
    基于Ajax的五子棋演示
    学习API HOOK,编写了一个winsock 的封包抓取程序,可免费使用;
    我得小猫爱摔交
    老是不中,算了算“双色球”和“3D”,全买到底要多少¥¥。。(C 代码)
    总算忙完了,大家'晚秋快乐'!
  • 原文地址:https://www.cnblogs.com/zcb123456789/p/13811628.html
Copyright © 2020-2023  润新知