1336: [Balkan2002]Alien最小圆覆盖
Time Limit: 1 Sec Memory Limit: 162 MBSec Special Judge
Submit: 1473 Solved: 648
[Submit][Status][Discuss]
Description
Input
先给出点的个数N,2<=N<=100000,再给出坐标Xi,Yi.(-10000.0<=xi,yi<=10000.0)
Output
Sample Input
6
8.0 9.0
4.0 7.5
1.0 2.0
5.1 8.7
9.0 2.0
4.5 1.0
Sample Output
5.00
5.00 5.00
随机增量法求最小圆覆盖。
三重循环。
令ci为前i个点的覆盖圆,新加入一个点i+1时,若其在圆内,跳过,若其在圆外,修改圆心使i+1在圆c(i+1)上。
检查之前的点,令ci为前i个点的覆盖圆,且点j在圆周上,若第i+1个点无法被圆覆盖,修改圆心使点i+1和点j都在圆周上。
检查之前的点,令ci为前i个点的覆盖圆,且点j和点k在圆周上,若第i+1个点无法被圆覆盖,修改圆心使点i+1和点j、点k都在圆周上
这算法倒是还能理解,但是求外心的几何算法表示看不懂。这个技能还是等高二再解锁吧。
代码目前只是过了样例,没有测过。
——辣鸡权限题!
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 const double eps=1e-8; 7 const int mxn=100000; 8 int n; 9 struct point{ 10 double x,y; 11 friend point operator +(const point a,const point b){ 12 return (point){a.x+b.x,a.y+b.y}; 13 } 14 friend point operator -(const point a,const point b){ 15 return (point){a.x-b.x,a.y-b.y}; 16 } 17 friend point operator /(const point a,double b){ 18 return (point){a.x/b,a.y/b}; 19 } 20 }p[mxn]; 21 inline double dis(point a,point b){ 22 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); 23 } 24 25 point center(point a,point b,point c){//返回三角形外心 26 double a1,a2,b1,b2,c1,c2; 27 point ans; 28 a1=2*(b.x-a.x);b1=2*(b.y-a.y);c1=(b.x*b.x)-(a.x*a.x)+(b.y*b.y)-(a.y*a.y); 29 //c1=(a1*a1+b1*b1)/2 30 a2=2*(c.x-a.x);b2=2*(c.y-a.y);c2=(c.x*c.x)-(a.x*a.x)+(c.y*c.y)-(a.y*a.y); 31 //c2=(a2*a2+b2*b2)/2 32 if(fabs(a1)<eps){ 33 ans.y=c1/b1; 34 ans.x=(c2-ans.y*b2)/a2; 35 } 36 else if(fabs(b1)<eps){ 37 ans.x=c1/a1; 38 ans.y=(c2-ans.x*a2)/b2; 39 } 40 else{ 41 ans.x=(c2*b1-c1*b2)/(a2*b1-a1*b2); 42 ans.y=(c2*a1-c1*a2)/(b2*a1-b1*a2); 43 } 44 return ans; 45 } 46 int main(){ 47 scanf("%d",&n); 48 int i,j,k; 49 for(i=1;i<=n;i++){ 50 scanf("%lf%lf",&p[i].x,&p[i].y); 51 } 52 random_shuffle(p+1,p+n+1); 53 point t=p[1]; 54 double r=0.0; 55 for(i=2;i<=n;i++)// 56 if(dis(t,p[i])>r+eps){ 57 t=(p[i]+p[1])/2;//默认圆心,等待增量 58 r=dis(p[i],t);//半径 59 for(j=2;j<i;j++)// 60 if(dis(t,p[j])>r+eps){//若有点在圆外,更新圆心 61 t=(p[i]+p[j])/2; 62 r=dis(t,p[i]); 63 for(k=1;k<j;k++){//最多三点确定一圆 64 if(dis(p[k],t)>r+eps){ 65 t=center(p[i],p[j],p[k]); 66 r=dis(p[i],t); 67 } 68 } 69 } 70 } 71 printf("%.10lf\n%.10lf %.10lf",r,t.x,t.y); 72 return 0; 73 }
时间: 2024-10-06 21:19:25