loj#6437. 「PKUSC2018」PKUSC(计算几何)

题面

传送门

题解

计算几何的东西我好像都已经忘光了……

首先我们可以把原问题转化为另一个等价的问题:对于每一个敌人,我们以原点为圆心,画一个经过该点的圆,把这个圆在多边形内部的圆弧的度数加入答案。求总的度数是多少

因为这是个简单多边形,我们可以把它给三角形剖分。就是说把每条边都和原点构成一个三角形,然后对圆计算这个三角形的贡献,根据这条边的顺逆时针顺序来决定贡献要加上还是减去。易知最后的贡献就是这个多边形的贡献

那么我们对于每一个圆,暴力枚举多边形的一条边和原点构成的三角形,然后判一下圆弧和三角形的交就行了

//minamoto
#include<bits/stdc++.h>
#define R register
#define eps 1e-3
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
    R int res,f=1;R char ch;
    while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
    for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
    return res*f;
}
double readdb()
{
    R double x=0,y=0.1,f=1;R char ch;
    while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
    for(x=ch-'0';(ch=getc())>='0'&&ch<='9';x=x*10+ch-'0');
    for(ch=='.'&&(ch=getc());ch>='0'&&ch<='9';x+=(ch-'0')*y,y*=0.1,ch=getc());
    return x*f;
}
const double Pi=acos(-1.0);const int N=505;
int n,m;double ans;
inline bool dcmp(const double &a,const double &b){return fabs(a-b)<eps;}
struct node{
	double x,y;
	node(){}
	node(R double X,R double Y):x(X),y(Y){}
	inline node operator +(const node &b)const{return node(x+b.x,y+b.y);}
	inline node operator -(const node &b)const{return node(x-b.x,y-b.y);}
	inline node operator *(const double &b)const{return node(x*b,y*b);}
	inline node operator /(const double &b)const{return node(x/b,y/b);}
	inline double operator *(const node &b)const{return x*b.y-y*b.x;}
	friend double dot(const node &a,const node &b){return a.x*b.x+a.y*b.y;}
	inline double norm(){return sqrt(x*x+y*y);}
}p[N],c[N];
void calc(node a,node b,double r){
	int f=(a*b<0)?-1:1;
	if(max(a.norm(),b.norm())<r)return;
	double theta=acos(dot(a,b)/(a.norm()*b.norm()));
	double h=fabs(a*b)/(b-a).norm();
	if(h>=r)return ans+=theta*f,void();
	double beta=acos(dot(a-b,node(-b.x,-b.y))/((a-b).norm()*b.norm()));
	double alpha=acos(dot(b-a,node(-a.x,-a.y))/((b-a).norm()*a.norm()));
	double t=asin(h/r),s=0;
	if(t>beta)s+=t-beta;if(t>alpha)s+=t-alpha;
	s=min(s,theta);
	ans+=f*s;
}
bool ck(node a,node b){
	node c(1,0);
	if(a.y<b.y)swap(a,b);
	return c*a>0&&b*c>0&&b*a>0;
}
void solve(){
	fp(i,1,m)if(!dcmp(c[i]*c[i+1],0))
		fp(j,1,n)if(!dcmp(p[j].norm(),0))calc(c[i],c[i+1],p[j].norm());
	fp(j,1,n)if(dcmp(p[j].norm(),0)){
		bool flag=1;int t=0;
		fp(i,1,m)if(dcmp((c[i]-p[j])*(c[i+1]-p[j]),0)){
			if(dot(c[i]-p[j],c[i+1]-p[j])<=0){flag=0;break;}
		}else{
			if(dcmp(c[i].y,0))t+=(c[i].x>0);
			else t+=ck(c[i],c[i+1]);
		}
		if(flag&&(t&1))ans+=2*Pi;
	}
	ans/=2*Pi;
	printf("%.5lf
",ans);
}
int main(){
//	freopen("testdata.in","r",stdin);
	n=read(),m=read();
	fp(i,1,n)p[i].x=readdb(),p[i].y=readdb();
	fp(i,1,m)c[i].x=readdb(),c[i].y=readdb();
	c[m+1]=c[1];
	solve();
	return 0;
}
原文地址:https://www.cnblogs.com/bztMinamoto/p/10486039.html