zoukankan      html  css  js  c++  java
  • bzoj 2618【半平面交模板】

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int N=505;
    int d,b,n,m;
    struct dian
    {
    	double x,y;
    	dian(double X=0,double Y=0)
    	{
    		x=X,y=Y;
    	}
    	dian operator + (const dian &a) const
    	{
    		return dian(x+a.x,y+a.y);
    	}
    	dian operator - (const dian &a) const
    	{
    		return dian(x-a.x,y-a.y);
    	}
    	dian operator * (const double &a) const
    	{
    		return dian(x*a,y*a);
    	}
    	dian operator / (const double &a) const
    	{
    		return dian(x/a,y/a);
    	}
    }a[N],p[N];
    struct bian
    {
    	dian s,v;//s表示向量的起点,v表示向量的方向和长度(从(0,0)射出)
    	bian(dian S=dian(),dian V=dian())
    	{
    		s=S,v=V;
    	}
    }l[N],q[N];
    double cj(dian a,dian b)//叉积
    {
    	return a.x*b.y-a.y*b.x;
    }
    double mj(dian a,dian b,dian c)//求有向面积
    {
    	return cj(b-a,c-a)/2.0;
    }
    dian jd(bian x,bian y)//求交点
    {
    	return x.s+x.v*(cj(x.s-y.s,y.v)/cj(y.v,x.v));	
    }
    bool px(bian x,bian y)//判断平行
    {
    	return cj(y.v,x.v)==0;
    }
    bool bn(bian x,bian y)//x在y的逆时针方向(平行先左后右
    {
    	double ar=cj(x.v,y.v);
    	return (ar>0)||((ar==0)&&cj(x.v,y.s-x.s)>0);
    }
    bool dn(dian x,bian y)//点在线的逆时针方向
    {
    	return cj(y.v,x-y.s)<=0;
    }
    bool cmp(const bian &x,const bian &y)//极角排序
    {
    	if(x.v.y==0&&y.v.y==0)//同与x轴平行
    		return x.v.x<y.v.x;
    	if((x.v.y<=0)==(y.v.y<=0))//同在x轴上或下(包括x轴)
    		return bn(x,y);
    	return x.v.y<y.v.y;//一上一下下在前
    }
    int main()
    {
    	scanf("%d",&d);
    	for(int i=1;i<=d;i++)
    	{
    		scanf("%d",&b);
    		for(int j=1;j<=b;j++)
    		{
    			int x,y;
    			scanf("%d%d",&x,&y);
    			p[n+j].x=x,p[n+j].y=y;//cout<<p[n+j].x<<" "<<p[n+j].y<<endl;
    			if(j!=1)
    				l[++m]=bian(p[n+j-1],p[n+j]-p[n+j-1]);
    		}
    		n+=b;
    		l[++m]=bian(p[n],p[n-b+1]-p[n]);
    	}
    	//半平面交
    	sort(l+1,l+m+1,cmp);
    	int top=0;
    	for(int i=1;i<=m;i++)
    	{
    		if(i==1||!px(l[i],l[i-1]))//去掉平行边
    			top++;
    		l[top]=l[i];
    	}
    	m=top;
    	int ll=1,rr=2;
    	q[1]=l[1],q[2]=l[2];
    	for(int i=3;i<=m;i++)//每次新加入向量,就会删掉在向量右边的交点(线上的也要删),维护的凸包首尾都是要删除的,最后还要模拟插入队头,把队尾中多余的半平面去掉
    	{
    		while(ll<rr&&dn(jd(q[rr],q[rr-1]),l[i]))
    			rr--;
    		while(ll<rr&&dn(jd(q[ll],q[ll+1]),l[i]))
    			ll++;
    		s[++rr]=l[i];
    	}
    	while(ll<rr&&dn(jd(q[rr],q[rr-1]),q[ll]))
    		rr--;//cout<<rr<<endl;
    	if(rr-ll<=1)
    	{
    		puts("0.000");
    		return 0;
    	}
    	top=0;
    	q[ll-1]=q[rr];
    	for(int i=ll;i<=rr;i++)
    		a[++top]=jd(q[i],q[i-1]);//求出相邻两边的交点,转化为凸包的记录方法
    	double ans=0.0;
    	for(int i=3;i<=top;i++)
    		ans+=mj(a[1],a[i-1],a[i]);
    	printf("%.3f
    ",ans);
    	return 0;
    }
    /*
    2
    6
    -2 0
    -1 -2
    1 -2
    2 0
    1 2
    -1 2
    4
    0 -3
    1 -1
    2 2
    -1 0
    */
    
  • 相关阅读:
    iOS resign code with App Store profile and post to AppStore
    HTTPS科普扫盲帖 对称加密 非对称加密
    appid 评价
    使用Carthage安装第三方Swift库
    AngularJS:何时应该使用Directive、Controller、Service?
    xcode7 The operation couldn't be completed.
    cocoapods pod install 安装报错 is not used in any concrete target
    xcode7 NSAppTransportSecurity
    learning uboot how to set ddr parameter in qca4531 cpu
    learning uboot enable protect console
  • 原文地址:https://www.cnblogs.com/lokiii/p/8503196.html
Copyright © 2011-2022 走看看