APIO2010 信號覆蓋


高清圖片,新窗口打開吧。

BZOJ持續陣亡。


我寫個暴力把外心的通式算出來了。。何必。。聯立解兩條直線就行了嘛。手推還容易錯。..


題解上說的還是比較清楚了。。


極角排序不能直接用叉乘。。 atan2吧,就是速度比較慢。先預處理出來atan2值,不要在cmp裏面算。


#include <cmath>
#include <cstdio>
#include <algorithm>
#define rep(i,l,r) for (int i=l;i<=r;++i)
typedef long long LL;
const int MAX_N=1505;
struct Point{
	int x,y;double angle;
	Point(int _x = 0,int _y = 0):x(_x),y(_y){}
	void read(){scanf("%d%d",&x,&y);}
};
Point operator -(const Point &a,const Point &b){return Point(a.x-b.x,a.y-b.y);}
LL Cross(const Point &a,const Point &b){return (LL)a.x*b.y-(LL)a.y*b.x;}
bool cmp_PolarAngle(const Point &a,const Point &b){return a.angle<b.angle;}
int n,top;
Point a[MAX_N],r[MAX_N];
LL Ao,Tu;
int main(){
	freopen("signaling.in","r",stdin);
	freopen("signaling.out","w",stdout);
	scanf("%d",&n);
	rep(i,1,n) a[i].read();
	rep(i,1,n){
		top=0;
		rep(j,1,n){
			if (i==j) continue;
			r[++top]=a[j]-a[i];
			r[top].angle=atan2(r[top].y,r[top].x);
			}
		std::sort(r+1,r+top+1,cmp_PolarAngle);
		LL res=(LL)(n-1)*(n-2)*(n-3)/6;
		int in=0,k=2;
		rep(j,1,top){
			if (j==k) k=k%top+1;
			while(Cross(r[j],r[k])>0)
				if (++in,++k>top) k-=top;
			if (in>=2) res-=(LL)(in-1)*in/2;
			if (in) in--;
			}
		Ao+=res;
		}
	Tu=(LL)n*(n-1)*(n-2)*(n-3)/24-Ao;
	printf("%f\n",(Ao+Tu*2)/((double)n*(n-1)*(n-2)/6)+3);
}


發佈了41 篇原創文章 · 獲贊 1 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章