zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    DiskFileUpload上传与Spring的CommonsMultipartResolver上传对比
    ajax请求jesery接口无法获取参数的问题解决方案
    java乱码问题总结
    indiGolog的安装
    hadoop启动步骤
    ubuntu修改默认jdk
    ubuntu 安装 ssh
    rabbitmq五种模式详解(含实现代码)
    终于可以像使用 Docker 一样丝滑地使用 Containerd 了
    Docker安装Nacos动态服务发现、配置和服务管理平台
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/10486039.html
Copyright © 2011-2022 走看看