BZOJ 1913: [Apio2010]signaling 信号覆盖

题目地址: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 
#include 
#include 

#define N 1500

using 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_JUDGE
	freopen("1913.in","r",stdin);
	freopen("1913.out","w",stdout);
	#endif
	scanf("%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;j1) 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

你可能感兴趣的:(BZOJ)