• LOJ#6437. 「PKUSC2018」PKUSC


    题面

    题意转化为:

    判断每个点所在的圆有多长的弧度角位于多边形内部。

    然后就很暴力了。

    每个点P,直接找到多边形和这个圆的所有交点,按照距离P的角度排序。

    找交点,直接联立二元二次方程组。。。。

    需要判断一段弧是否在多边形内部。

    向量随机旋转角度,判断点是否在多边形内部即可。

    如果该点在多边形边上,返回-1,重新旋转。

    由于double,所以不会出现射线在多边形边上情况。

    注意:

    (0,0)要特判是否在多边形内部。+eps判断

    #include<bits/stdc++.h>
    #define reg register int
    using namespace std;
    // using namespace Modulo;
    namespace Miracle{
    const int N=505;
    const double eps=1e-8;
    const double inf=1e8;
    const double Pi=acos(-1);
    int n,m;
    struct po{
        double x,y;
        po(){}
        po(double xx,double yy){
            x=xx;y=yy;
        }
        double friend operator *(po a,po b){
            return a.x*b.y-a.y*b.x;
        }
        double dis(){
            return sqrt(x*x+y*y);
        }
        po friend operator -(po a,po b){
            return po(a.x-b.x,a.y-b.y);
        }
        double deg(){
            return atan2(y,x);
        }
        po xuan(double d){
            double nd=deg()-d;
            double len=dis();
            return po(len*cos(nd),len*sin(nd));
        }
        void op(){
            cout<<"("<<x<<","<<y<<")"<<endl;
        }
    }p[N],q[N];
    struct node{
        po P;
        double c;
        node(){}
        node(double cc,po PP){
            c=cc;P=PP;
        }
        bool friend operator <(node a,node b){
            return a.c<b.c;
        }
    }cur[N];
    struct line{
        double k,b;
        po A,B;
        double f(double x){
            if(k<inf) return k*x+b;
            return A.y;
        }
    }l[N];
    bool on(po c,line L){//c on L?
        if(c.x+eps>=L.A.x&&c.x<=L.B.x+eps){
            if(L.k==inf) {
                if(c.y+eps>=L.A.y&&c.y<=L.B.y+eps) return 1;
            }
            else{double ny=L.f(c.x);
            if(fabs(ny-c.y)<eps) return 1;}
        }
        return 0;
    }
    bool jiao(line a,line b){
        double c1=(a.A-b.A)*(a.A-b.B),c2=(a.B-b.A)*(a.B-b.B);
        double c3=(b.A-a.A)*(b.A-a.B),c4=(b.B-a.A)*(b.B-a.B);
        if(c1*c2<=0&&c3*c4<=0) return true;
        return false;
    }
    int in(po a){
        int cnt=0;
        line now;
        now.k=0;now.b=a.y;
        now.A=a;now.B=po(inf,a.y);
        for(reg i=1;i<=m;++i){
            if(on(a,l[i])) return -1;
            if(jiao(now,l[i])) ++cnt;
        }
        if(cnt&1) return 1;
        return 0;
    }
    double cha(double d1,double d2){
        if(d1>=0&&d2<=0){
            return d1-d2;
        }else if(d1>=0&&d2>=0){
            if(d1>d2) return d1-d2;
            return 2*Pi-(d2-d1);
        }else if(d1<=0&&d2>=0){
            return 2*Pi-(d2-d1);
        }else if(d1<=0&&d2<=0){
            if(d1>d2) return (d1-d2);
            return 2*Pi-(d2-d1);
        }
        return 0;
    }
    double sui(){
        return (double)rand()/(RAND_MAX);
    }
    double calc(po a){
        int cnt=0;
        double r=a.dis();
        if(r==0){
            a.y+=eps;
            if(in(a)==1) return 2*Pi;
            else return 0;
        }
        for(reg i=1;i<=m;++i){
            if(l[i].k<inf){
                double A=(1+l[i].k*l[i].k);
                double B=2*l[i].k*l[i].b;
                double C=l[i].b*l[i].b-r*r;
                double deta=B*B-4*A*C;
                if(deta>=0){
                    double x1=(-B+sqrt(deta))/(2*A),x2=(-B-sqrt(deta))/(2*A);
                    po now=po(x1,l[i].f(x1));
                    if(on(now,l[i])) {
                        cur[++cnt]=node(cha(a.deg(),now.deg()),now);
                    }
                    now=po(x2,l[i].f(x2));
                    if(on(now,l[i])){
                        cur[++cnt]=node(cha(a.deg(),now.deg()),now);
                    }
                }
            }else{
                double lp=r*r-l[i].A.x*l[i].A.x;
                double X=l[i].A.x;
                if(lp>0){
                    double Y=sqrt(lp);
                    po now=po(X,Y);
                    if(on(now,l[i])) {
                        cur[++cnt]=node(cha(a.deg(),now.deg()),now);
                    }
                    Y=-sqrt(lp);
                    now=po(X,Y);
                    if(on(now,l[i])){
                        cur[++cnt]=node(cha(a.deg(),now.deg()),now);
                    }
                }
            }
        }
        
        cur[++cnt]=node(0,a);
        cur[++cnt]=node(2*Pi,a);
        sort(cur+1,cur+cnt+1);
        double ret=0;
        for(reg i=2;i<=cnt;++i){
            double d=cur[i].c-cur[i-1].c;
            if(d<0.0000001) continue;
            po now=cur[i-1].P;
            int tmp=-1;
            while(tmp==-1){
                double z=d*sui();
                now=cur[i-1].P.xuan(z);
                tmp=in(now);
            }
            if(tmp==1){
                ret+=d;
            }
        }
        return ret;
    
    }
    int main(){
        srand((unsigned long long)new char);
        cin>>n>>m;
        for(reg i=1;i<=n;++i){
            double x,y;
            scanf("%lf%lf",&x,&y);
            q[i]=po(x,y);
        }
        for(reg i=1;i<=m;++i){
            double x,y;
            scanf("%lf%lf",&x,&y);
            p[i]=po(x,y);
        }
        for(reg i=1;i<=m;++i){
            int nxt=(i==m)?1:i+1;
            l[i].A=p[i];l[i].B=p[nxt];
            if(p[i].x>p[nxt].x||(p[i].x==p[nxt].x&&p[i].y>p[nxt].y)) swap(l[i].A,l[i].B);
    
            if(p[i].x==p[nxt].x){
                l[i].k=inf;
            }else{
                l[i].k=(p[nxt].y-p[i].y)/(p[nxt].x-p[i].x);
                l[i].b=((p[nxt].x*p[i].y)-(p[i].x*p[nxt].y))/(p[nxt].x-p[i].x);
            }
        }
    
        double ans=0.0;
        for(reg i=1;i<=n;++i){
            ans+=calc(q[i]);
        }
        ans=ans/(2*Pi);
        printf("%.5lf",ans);
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
    */
  • 相关阅读:
    2021.02.09 【ABAP随笔】-Excel高效输出工具-xlsx workbench-输出多个Sheet
    2021.02.07 【ABAP随笔】-Excel高效输出工具-xlsx workbench
    Thrift did not exit cleanly
    Docker部署Springboot项目,Invalid or corrupt jarfile /app.jar
    为jenkins设置nginx作为反向代理
    Jenkins安装报错 No valid crumb was included in request
    判断当前设备是ios还是安卓
    vue 路由跳转四种方式 (带参数)
    Vue table的column属性,render函数生成switch开关和button按钮
    H5页面自定义 pxTorem 函数进行单位转换
  • 原文地址:https://www.cnblogs.com/Miracevin/p/11021938.html
Copyright © 2020-2023  润新知