ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【CF528E】Triangles 3000(计算几何)

2019-07-10 14:50:41  阅读:297  来源: 互联网

标签:CF528E ch return 直线 double times Vect 3000 Triangles


【CF528E】Triangles 3000(计算几何)

题面

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

题解

如果一定考虑直接计算这个三角形的面积,我们很难不去弄出这三个交点。
我们需要的是低于\(O(n^3)\)的复杂度,而\(O(n^3)\)的做法可以直接暴力枚举三条直线。
考虑向量计算面积的方法,对于一个在三角形\(\Delta ABC\)之外的点\(O\),我们可以有:
\[S\Delta ABC=\frac{1}{2}(OA\times OB+OB\times OC+OC\times OA)\]
这个证明不难,画图把每一部分的面积表示出来就很简单了。
接下来枚举一条直线,剩下点按照极角顺序依次加入,然后这个贡献可以拆成三个部分,而我们只算都在枚举的直线上的交点的贡献,在其他直线上的可以在其他时候算。
于是要求的就是这条直线和枚举的直线的交点与前面所有直线与枚举的直线的交点与\(O\)构成的向量的叉积。
叉积是:\((x1,y1)\times (x2,y2)=x1*y2-x2*y1\),
于是得到:\((x1,y1)\times (x2,y2)+(x1,y1)\times (x3,y3)=x1*(y2+y3)-y1*(x2+x3)\)
这个东西显然等于\((x1,y1)\times ((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\n",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\n",ans);
    return 0;
}

标签:CF528E,ch,return,直线,double,times,Vect,3000,Triangles
来源: https://www.cnblogs.com/cjyyb/p/11163840.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有