题意转化为:
判断每个点所在的圆有多长的弧度角位于多边形内部。
然后就很暴力了。
每个点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* */