bzoj2823 信号塔 随机增量算法

       看WC课件好像zhj的ppt里面有这道题目?然而讲得太简略了看不懂。

       然后扒了扒黄学长的代码发现好像很简单。。。

       实际上就是暴力枚举三个点,枚举到第i个点时看能不能放到当前的圆里面,不能就移前面i-1个点和i组成一个圆。注意这里i<=3。然后推一下外心就好了。

       考虑每一个节点,在边上的期望概率为(1/N),然后枚举完第一个点,当且仅当它在边上才会继续枚举第二个点。如果枚举第二个点之后的期望时间复杂度为O(N),那么对于第一个点时间复杂度为O(N*1/N*N)=O(N)。显然枚举第三个点是O(N)的,因此同理枚举第二个点是O(N),第一个也是O(N)。

       一开始的时候随机打乱。(虽然这样好像变慢呢?)

AC代码如下:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#define eps 1e-6
using namespace std;

struct point{ double x,y; }a[500005]; int n;
double dist(point u,point v){
	return sqrt((u.x-v.x)*(u.x-v.x)+(u.y-v.y)*(u.y-v.y));
}
point centre(point u,point v){
	u.x=(u.x+v.x)/2; u.y=(u.y+v.y)/2; return u;
}
double sqr(point u){ return u.x*u.x+u.y*u.y; }
point calc(double x,double y,double z,double u,double v,double w){
	point t; t.x=(z*v-w*y)/(x*v-u*y); t.y=(z-t.x*x)/y;
	return t;
}
point centre(point u,point v,point w){
	double p=sqr(u)/2,q=sqr(v)/2,t=sqr(w)/2;
	return calc(u.x-v.x,u.y-v.y,p-q,u.x-w.x,u.y-w.y,p-t);
}
int main(){
	srand(20160301); scanf("%d",&n); int i,j,k;
	for (i=1; i<=n; i++){
		scanf("%lf%lf",&a[i].x,&a[i].y);
		if (i>1) swap(a[i],a[rand()%(i-1)+1]);
	}
	point o=a[1]; double r=0;
	for (i=2; i<=n; i++) if (dist(o,a[i])>r+eps){
		o=centre(a[1],a[i]); r=dist(o,a[i]);
		for (j=1; j<i; j++) if (dist(o,a[j])>r+eps){
			o=centre(a[i],a[j]); r=dist(o,a[j]);
			for (k=1; k<j; k++) if (dist(o,a[k])>r+eps){
				o=centre(a[i],a[j],a[k]); r=dist(o,a[k]);
			}
		}
	}
	printf("%.2f %.2f %.2f\n",o.x,o.y,r);
	return 0;
}


by lych

2016.3.1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值