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*
*/

 

posted @ 2019-06-14 10:11  *Miracle*  阅读(300)  评论(0编辑  收藏  举报