题意转化为:
判断每个点所在的圆有多长的弧度角位于多边形内部。
然后就很暴力了。
每个点P,直接找到多边形和这个圆的所有交点,按照距离P的角度排序。
找交点,直接联立二元二次方程组。。。。
需要判断一段弧是否在多边形内部。
向量随机旋转角度,判断点是否在多边形内部即可。
如果该点在多边形边上,返回-1,重新旋转。
由于double,所以不会出现射线在多边形边上情况。
注意:
(0,0)要特判是否在多边形内部。+eps判断
#include#define reg register intusing 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<<"("< <<","< <<")"< =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) =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 =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**/