codeforces528E Triangles 3000

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yzyyylx/article/details/88093228

题面

题意

在平面上有n条直线,随机选择三条,其面积的期望大小是多少。

做法

很显然,面积的期望要转化为所有三角形的面积和除以 ( n 3 ) n\choose3 ,考虑计算三角形的面积和。
可以把三角形ABC的面积转化为(OA×OB+OB×OC+OC×OA)/2,这样只要分别计算这几个叉积的和即可。
经过观察不难发现,如果OA,OB的叉积会被计算,当且仅当A,B两点都在某条给出的直线上 ,因此我们可以枚举所有直线,计算直线上的交点两两的叉积和。
要注意叉积是有方向的,不满足交换律,这就意味着如果将点随意相乘会导致答案错误。所以要先对所有直线根据斜率排序,保证对于一个三角形上的三个点被逆时针加入,代码还是比较好理解的。

代码

#include<bits/stdc++.h>
#define db double
#define eps 1e-8
#define N 3010
using namespace std;

int n;
db x,y,sx,sy,ans;
struct Xn
{
    db a,b,c;
    bool operator < (const Xn &u) const
    {
		if(fabs(b)<eps) return 1;
		if(fabs(u.b)<eps) return 0;
		return a/b<u.a/u.b;
    }
}xn[N];

int main()
{
    int i,j;
    cin>>n;
    for(i=1;i<=n;i++) scanf("%lf%lf%lf",&xn[i].a,&xn[i].b,&xn[i].c);
    sort(xn+1,xn+n+1);
    for(i=1;i<=n;i++)
    {
		sx=sy=0;
		for(j=i%n+1;j!=i;j=j%n+1)
		{
		    x=(xn[j].c*xn[i].b-xn[i].c*xn[j].b)/(xn[i].a*xn[j].b-xn[j].a*xn[i].b);
		    y=(xn[j].c*xn[i].a-xn[i].c*xn[j].a)/(xn[j].a*xn[i].b-xn[i].a*xn[j].b);
		    //x,y表示i,j两条直线的交点
		    ans+=x*sy-y*sx;
		    sx+=x,sy+=y;
		}
    }
    printf("%.12f",ans*3/n/(n-1)/(n-2));
}

猜你喜欢

转载自blog.csdn.net/yzyyylx/article/details/88093228
今日推荐