BZOJ 1913: [Apio2010]signaling 信号覆盖

来源:互联网 发布:喊麦用什么软件 编辑:程序博客网 时间:2024/04/30 00:25

题目地址:http://www.lydsy.com/JudgeOnline/problem.php?id=1913

题目大意:一个平面上n个点,随机选3个点构成一个圆,问期望有多少个点在这个圆内和圆上。数据保证没有4点共圆、3点共线和重点。

算法讨论:考虑四边形,凸四边形对答案的贡献为2,凹四边形对答案的贡献为1。设凹四边形个数为a,凸四边形个数为b,那么b=C(n,4)-a。枚举凹四边形的中间点,以中间点为原点,把其他点按照极角排序,枚举极角差刚刚不小于π的两条边,那么这两条边之间的点和其中一条边上的点不包含中间点。由于按照极角排序,那么枚举的时间复杂度是O(n)。设p为不包含中间点的三角形个数,那么以该点为中间点的凹四边形个数为C(n-1,3)-p。最后的期望即为(a+2*b)/C(n,3)。

Code:

#include <cmath>#include <cstdio>#include <algorithm>#define N 1500using namespace std;const long double pi=acos(-1);int n,cnt;double tx,ty;long long p,q;long double x[N+10],y[N+10],point[N*2+10];int main(){#ifndef ONLINE_JUDGEfreopen("1913.in","r",stdin);freopen("1913.out","w",stdout);#endifscanf("%d",&n);if (n<4){puts("0");return 0;}for (int i=1;i<=n;++i) scanf("%lf%lf",&tx,&ty),x[i]=(long double)tx,y[i]=(long double)ty;for (int i=1;i<=n;++i){int cnt=0;long long res=0;for (int j=1;j<=n;++j) if (i!=j) point[++cnt]=atan2(x[j]-x[i],y[j]-y[i]);sort(point+1,point+cnt+1);for (int j=1;j<n;++j) point[++cnt]=point[j]+pi*2;for (int j=1,k=0;j<n;++j){k=max(k,j+1);while (k<=cnt && point[k]<point[j]+pi) k++;if (k-j-1>1) res+=(k-j-1)*(k-j-2)/2;}p+=(long long)(n-1)*(n-2)*(n-3)/6-res;}q=(long long)n*(n-1)*(n-2)*(n-3)/24-p;printf("%.6lf\n",(double)((long double)(p+2*q)/((long long)n*(n-1)*(n-2)/6)+3));return 0;}

By Charlie Pan

Aug 25,2014

0 0
原创粉丝点击