題面
題意
在平面上有n條直線,隨機選擇三條,其面積的期望大小是多少。
做法
很顯然,面積的期望要轉化爲所有三角形的面積和除以,考慮計算三角形的面積和。
可以把三角形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));
}