• 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
    */
    
  • 相关阅读:
    Chamfer Distance--倒角距离
    javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
    mysql单个索引和联合索引的区别
    鸽一下
    笔记:关于 INT1 INT0 中断说明记录 (2020-07-16)[85.22%]
    使用 Git 管理 KiCad EDA 项目文件 [2020-06-28][26.77%]
    从单片机基础到程序框架 2019版(2020-07-04)[12.66%]
    KiCad Pcbnew 中现代工具箱 (2020-06-24)[98.33%]
    【营养研究一】鸡蛋和牛奶的营养对比 (2020-06-23)[95.89%]
    git 忽略上传指定文件 命令
  • 原文地址:https://www.cnblogs.com/lokiii/p/8503196.html
Copyright © 2020-2023  润新知