ZOJ1450 Minimal Circle
不断添加圆,维护最小圆。如果添加的点i在圆内,不动,否则:
问题转化为求1~I的最小圆:求出1与I的最小圆,并且扫描j=2~(I-1),维护(1)+(i)+(2~j)的最小圆,如果找到J不在最小圆内,问题转化为:求(1~J)+(i)的最小圆。求出I与J的最小圆,继续扫描K=1~(j-1),找到不在最小圆内的,求出I J K三者最小圆,此时找到了(1~j)+(i)的最小圆,可以回到上一步(三点定一圆,所以1~(J-1)一定都在求出的最小圆上)。
这个做法复杂度是O(n)的,当加入圆的顺序随机时,因为三点定一圆,所以不在圆内概率是3/i,求出期望可得是On.
以上是百度文库的内容,自己做了些删改
以下代码的时间是10ms,内存180kb
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> struct point { double x; double y; }; struct T { point heart; double d; }circle; point a[102]; double dis(point a,point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } bool check(point p,point q,point k)//确定三点是否在同一直线上 { if((p.x-k.x)*(q.y-k.y)-(q.x-k.x)*(p.y-k.y)==0) { return true; } return false; } void fin2(point p,point q,int n) { int i; circle.heart.x=(p.x+q.x)/2; circle.heart.y=(p.y+q.y)/2; circle.d=dis(p,q)/2; for(i=1;i<=n;i++) { if(dis(a[i],circle.heart)<=circle.d) { continue; } if(check(p,q,a[i]))//三点一线 { double d[3]; d[0]=dis(q,p); d[1]=dis(q,a[i]); d[2]=dis(p,a[i]); if(d[0]>=d[1]&&d[0]>=d[2]) { circle.heart.x=(p.x+q.x)/2; circle.heart.y=(p.y+q.y)/2; circle.d=d[0]/2; } else if(d[1]>=d[0]&&d[1]>=d[2]) { circle.d=d[1]/2; circle.heart.x=(q.x+a[i].x)/2; circle.heart.y=(q.y+a[i].y)/2; } else { circle.d=d[2]/2; circle.heart.x=(p.x+a[i].x)/2; circle.heart.y=(p.y+a[i].y)/2; } } else { double c1=(p.x*p.x+p.y*p.y-q.x*q.x-q.y*q.y)/2.0; double c2=(p.x*p.x+p.y*p.y-a[i].x*a[i].x-a[i].y*a[i].y)/2.0; circle.heart.x=(c1*(p.y-a[i].y)-c2*(p.y-q.y))/((p.x-q.x)*(p.y-a[i].y)-(p.x-a[i].x)*(p.y-q.y)); circle.heart.y=(c1*(p.x-a[i].x)-c2*(p.x-q.x))/((p.y-q.y)*(p.x-a[i].x)-(p.y-a[i].y)*(p.x-q.x)); circle.d=dis(circle.heart,p); } } } void fin(point p,int n) { circle.heart.x=(a[1].x+p.x)/2; circle.heart.y=(a[1].y+p.y)/2; circle.d=dis(p,a[1])/2; int i; for(i=2;i<=n;i++) { if(dis(a[i],circle.heart)>circle.d) { fin2(p,a[i],i-1); } } } int main() { int n; while(scanf("%d",&n),n) { int i,j; for(i=1;i<=n;i++) { scanf("%lf %lf",&a[i].x,&a[i].y); } if(n==1) { printf("%.2f %.2f 0.00\n",a[0].x,a[0].y); continue; } circle.heart.x=(a[1].x+a[2].x)/2; circle.heart.y=(a[1].y+a[2].y)/2; circle.d=dis(a[2],a[1])/2; for(i=3;i<=n;i++) { if(dis(circle.heart,a[i])>circle.d) { fin(a[i],i-1); } } printf("%.2f %.2f %.2f\n",circle.heart.x,circle.heart.y,circle.d); } return 0; }