zoukankan      html  css  js  c++  java
  • 【CF528E】Triangles 3000(计算几何)

    【CF528E】Triangles 3000(计算几何)

    题面

    CF
    平面上有若干条直线,保证不平行,不会三线共点。
    求任选三条直线出来围出的三角形的面积的期望。

    题解

    如果一定考虑直接计算这个三角形的面积,我们很难不去弄出这三个交点。
    我们需要的是低于(O(n^3))的复杂度,而(O(n^3))的做法可以直接暴力枚举三条直线。
    考虑向量计算面积的方法,对于一个在三角形(Delta ABC)之外的点(O),我们可以有:

    [SDelta ABC=frac{1}{2}(OA imes OB+OB imes OC+OC imes OA) ]

    这个证明不难,画图把每一部分的面积表示出来就很简单了。
    接下来枚举一条直线,剩下点按照极角顺序依次加入,然后这个贡献可以拆成三个部分,而我们只算都在枚举的直线上的交点的贡献,在其他直线上的可以在其他时候算。
    于是要求的就是这条直线和枚举的直线的交点与前面所有直线与枚举的直线的交点与(O)构成的向量的叉积。
    叉积是:((x1,y1) imes (x2,y2)=x1*y2-x2*y1)
    于是得到:((x1,y1) imes (x2,y2)+(x1,y1) imes (x3,y3)=x1*(y2+y3)-y1*(x2+x3))
    这个东西显然等于((x1,y1) imes ((x2,y2)+(x3,y3))),那么就可以很开心的前缀和了。
    注意为了保证顺序正确,需要把所有的直线按照极角提前排序。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    #define MAX 3030
    inline int read()
    {
    	int x=0;bool t=false;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=true,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return t?-x:x;
    }
    int n;double ans;
    struct Vect{double x,y;}O,g[MAX];
    struct Line{double a,b,c,ang;}L[MAX];
    bool operator<(Line a,Line b){return a.ang<b.ang;}
    Vect Intersection(Line a,Line b)
    {
    	if(fabs(a.a)>1e-9)
    	{
    		double y=(b.c*a.a-a.c*b.a)/(a.b*b.a-a.a*b.b);
    		double x=-(a.c+a.b*y)/a.a;
    		return (Vect){x,y};
    	}
    	else
    	{
    		double x=(b.c*a.b-a.c*b.b)/(a.a*b.b-a.b*b.a);
    		double y=-(a.c+a.a*x)/a.b;
    		return (Vect){x,y};
    	}
    }
    double Cross(Vect a,Vect b){return a.x*b.y-a.y*b.x;}
    Vect operator-(Vect a,Vect b){return (Vect){a.x-b.x,a.y-b.y};}
    Vect operator+(Vect a,Vect b){return (Vect){a.x+b.x,a.y+b.y};}
    bool cmp(Vect a,Vect b){return Cross(a,b)>=0;}
    int main()
    {
    	n=read();O=(Vect){1e7,1e7};
    	for(int i=1;i<=n;++i)
    	{
    		L[i].a=read(),L[i].b=read(),L[i].c=-read();
    		double x,y;
    		if(fabs(L[i].b)>1e-7)x=1,y=-L[i].a/L[i].b;
    		else y=1,x=-L[i].b/L[i].a;
    		L[i].ang=atan2(y,x);
    	}
    	sort(&L[1],&L[n+1]);
    	/*
    	for(int i=1;i<=n;++i)
    		for(int j=i+1;j<=n;++j)
    			for(int k=j+1;k<=n;++k)
    			{
    				Vect g[3];
    				g[0]=Intersection(L[i],L[j]);
    				g[1]=Intersection(L[j],L[k]);
    				g[2]=Intersection(L[k],L[i]);
    				ans-=(Cross(g[0],g[1])+Cross(g[1],g[2])+Cross(g[2],g[0]));
    			}
    	ans/=1.0*n*(n-1)*(n-2)/3;
    	printf("%.10lf
    ",ans);ans=0;
    	*/
    	for(int i=1;i<=n;++i)
    	{
    		Vect s=(Vect){0,0};
    		for(int j=i%n+1;j!=i;j=j%n+1)
    		{
    			Vect a=Intersection(L[i],L[j]);
    			ans+=Cross(s,a);s=s+a;
    		}
    	}
    	ans/=1.0*n*(n-1)*(n-2)/3;
    	printf("%.10lf
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    eclips搭建python开发环境
    win7下odoo服务启动又停止解决方法
    ubuntu14.04调节屏幕亮度
    在ubunut下使用pycharm和eclipse进行python远程调试
    读书笔记——乔布斯,做最好的自己,共创式教练
    压力测试工具——Galting
    番茄工作法和Bullet Journal笔记法
    Openstack Swift中间件编写
    《黑客》读书笔记
    用腻了bootstrap的可以试试semantic-ui
  • 原文地址:https://www.cnblogs.com/cjyyb/p/11163840.html
Copyright © 2011-2022 走看看