• [NOI.AC省选模拟赛3.31] 星辰大海 [半平面交]


    题面

    传送门

    思路

    懒得解释了......也是比较简单的结论

    但是自己看到几何就退缩了......

    下周之内写一个计算几何的学习笔记!

    Code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cassert>
    #include<cmath>
    #define eps 1e-14
    using namespace std;
    inline int read(){
    	int re=0,flag=1;char ch=getchar();
    	while(!isdigit(ch)){
    		if(ch=='-') flag=-1;
    		ch=getchar();
    	}
    	while(isdigit(ch)) re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
    	return re*flag;
    }
    /*
    Calculating the intersection of two segments:
    method 1:	Brute force implemention -> get 4 equations, take the position of target point as the unknown factor
    method 2:	Solve using vector -> the 'x-multiple' of two planary vectors is the SIGNED area of the paralellogram formed by them.
    			ALWAYS MIND the sign before the area (refer to function cross(seg,seg) for further detail)
    */
    int T,N,n,m;
    inline int sign(const long double &d){
    	if(d>eps) return 1;
    	if(d<-eps) return -1;
    	return 0;
    }
    struct p{
    	long double x,y;
    	p(long double xx=0.0,long double yy=0.0){x=xx;y=yy;}
    }rt[1000010];
    inline p operator *(const p &a,const long double &b){return p(a.x*b,a.y*b);}
    inline long double operator *(const p &a,const p &b){return a.x*b.y-a.y*b.x;}//'x-multiple' of planary vector
    inline p operator -(const p &a,const p &b){return p(a.x-b.x,a.y-b.y);}
    inline p operator +(const p &a,const p &b){return p(a.x+b.x,a.y+b.y);}
    struct ele{
    	p a;long double k;
    }lis[1000010];
    struct seg{
    	p a,b;long double k;
    	seg(p aa=p(),p bb=p(),long double kk=0.0){a=aa;b=bb;k=kk;}
    }a[1000010],q[1000010];
    inline long double getk(const p &a){return atan2l(a.y,a.x);}//get the k-value of a pair<long double,dobule>
    inline bool cmp(const ele &l,const ele &r){return l.k<r.k;}
    inline bool operator <(const seg &l,const seg &r){return l.k<r.k;}//sort according to k
    inline p cross(const seg &x,const seg &y){//calculate the intersection using planary vector
    	long double v1=(x.a-y.b)*(x.b-y.b);
    	long double v2=(x.a-y.a)*(x.b-y.a);
    	long double c=v1/(v1-v2);
    	p re=(y.b+((y.a-y.b)*c));
    	return re;
    }
    inline bool right(const p &x,const seg &y){//determine if x is to the right of y
    	return ((x-y.a)*(x-y.b))>=0;
    }
    inline long double solve(){
    	int i,head=1,tail=0,flag;long double re=0;
    	sort(a+1,a+m+1);
    	for(i=1;i<=m;i++){
    		flag=0;
    		while(head<=tail&&(!sign(a[i].k-q[tail].k))){//get rid of segments at same k
    			if((q[tail].a-a[i].a)*(q[tail].a-a[i].b)>=0) tail--;//if old one is to the right of current one, delete it
    			else{flag=1;break;}//or else, the current one shall be deleted
    		}
    		if(flag) continue;
    		while(head<tail&&right(rt[tail],a[i])) tail--;//check if the intersection is to the right, if so delete the foremost/backmost segment
    		while(head<tail&&right(rt[head+1],a[i])) head++;
    		q[++tail]=a[i];
    		if(head<tail) rt[tail]=cross(q[tail-1],q[tail]);
    	}
    	while(head<tail&&right(rt[tail],q[head])) tail--;
    	while(head<tail&&right(rt[head+1],q[tail])) head++;
    	rt[head]=rt[tail+1]=cross(q[head],q[tail]);//mind that the first and last points are adjacent
    	for(i=head;i<=tail;i++){
    		re+=rt[i]*rt[i+1];
    	}
    	return re;
    }
    const long double pi=acosl(-1.0);
    const p ur(1e6,1e6);
    const p ul(-1e6,1e6);
    const p dr(1e6,-1e6);
    const p dl(-1e6,-1e6);
    const seg rr(ur,dr,-pi*0.5);
    const seg dd(dr,dl,pi);
    const seg ll(dl,ul,pi*0.5);
    const seg uu(ul,ur,0);
    int main(){
    	N=read();T=read();int flag,i,j;
    	while(T--){
    		n=read();
    		m=0;
    		a[++m]=rr;a[++m]=dd;a[++m]=ll;a[++m]=uu;
    		for(i=1;i<=n;i++){
    			lis[i].a.x=read();
    			lis[i].a.y=read();
    		}
    		for(i=2;i<=n;i++){
    			lis[i].k=getk(lis[i].a-lis[1].a);
    		}
    		sort(lis+2,lis+n+1,cmp);
    		for(i=2;i<=n;i++){
    			lis[i+n-1]=lis[i];
    			lis[i+n-1].k+=2.0*pi;
    		}
    		flag=1;j=2;
    		for(i=2;i<=n;i++){
    			j=max(i,j);
    			while(lis[j+1].k-lis[i].k<pi+eps) j++;
    			if((!sign(lis[i+1].k-lis[i].k))||(!sign(lis[i].k+pi-lis[j].k))){
    				flag=0;puts("0");break;
    			}
    			if(j!=i) a[++m]=seg(lis[j].a,lis[i].a,getk(lis[i].a-lis[j].a));
    			if(lis[i+1].k-lis[i].k<pi+eps) a[++m]=seg(lis[i+1].a,lis[i].a,getk(lis[i].a-lis[i+1].a));
    		}
    		if(flag) printf("%.9lf
    ",(double)solve()*0.5);
    	}
    }
    
  • 相关阅读:
    docker搭建本地仓库并制作自己的镜像
    docker命令及操作
    从零开始学android开发-项目打包发布
    从零开始学android开发-adt-bundle-eclipse下的修改android app名称
    从零开始学android开发-项目重命名
    Android Studio系列教程一--下载与安装
    Axure RP 7.0注册码
    MVC网站发布常见问题
    无间断滚动的新闻文章列表
    @HTML
  • 原文地址:https://www.cnblogs.com/dedicatus545/p/10633540.html
Copyright © 2020-2023  润新知