codeforces528E Triangles 3000

題面

題意

在平面上有n條直線,隨機選擇三條,其面積的期望大小是多少。

做法

很顯然,面積的期望要轉化爲所有三角形的面積和除以(n3)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));
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章