题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=450
You are to write a program to find a circle which covers a set of points and has the minimal area. There will be no more than 100 points in one problem.
题意描述:找到一个最小圆能够包含到所有的二维坐标点。
算法分析:最小覆盖圆的做法。
1 //最小覆盖圆 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<cstdlib> 6 #include<cmath> 7 #include<algorithm> 8 #define inf 0x7fffffff 9 #define exp 1e-10 10 #define PI 3.141592654 11 using namespace std; 12 const int maxn=1000+10; 13 struct Point 14 { 15 double x,y; 16 Point(double x=0,double y=0):x(x),y(y){} 17 }an[maxn],d;//d:最小覆盖圆的圆心坐标 18 double r;//最小覆盖圆的半径 19 typedef Point Vector; 20 Vector operator + (Vector A,Vector B) {return Vector(A.x+B.x , A.y+B.y); } 21 Vector operator - (Vector A,Vector B) {return Vector(A.x-B.x , A.y-B.y); } 22 Vector operator * (Vector A,double p) {return Vector(A.x*p , A.y*p); } 23 Vector operator / (Vector A,double p) {return Vector(A.x/p , A.y/p); } 24 int dcmp(double x) 25 { 26 if (fabs(x)<exp) return 0; 27 return x<0 ? -1 : 1; 28 } 29 double cross(Vector A,Vector B) 30 { 31 return A.x*B.y-B.x*A.y; 32 } 33 double dist(Vector A,Vector B) 34 { 35 double x=(A.x-B.x)*(A.x-B.x); 36 double y=(A.y-B.y)*(A.y-B.y); 37 return sqrt(x+y); 38 } 39 40 void MiniDiscWith2Point(Point p,Point q,int n) 41 { 42 d=(p+q)/2.0; 43 r=dist(p,q)/2; 44 int k; 45 double c1,c2,t1,t2,t3; 46 for (k=1 ;k<=n ;k++) 47 { 48 if (dist(d,an[k])<=r) continue; 49 if (dcmp(cross(p-an[k],q-an[k]))!=0) 50 { 51 c1=(p.x*p.x+p.y*p.y-q.x*q.x-q.y*q.y)/2.0; 52 c2=(p.x*p.x+p.y*p.y-an[k].x*an[k].x-an[k].y*an[k].y)/2.0; 53 d.x=(c1*(p.y-an[k].y)-c2*(p.y-q.y))/((p.x-q.x)*(p.y-an[k].y)-(p.x-an[k].x)*(p.y-q.y)); 54 d.y=(c1*(p.x-an[k].x)-c2*(p.x-q.x))/((p.y-q.y)*(p.x-an[k].x)-(p.y-an[k].y)*(p.x-q.x)); 55 r=dist(d,an[k]); 56 } 57 else 58 { 59 t1=dist(p,q); 60 t2=dist(q,an[k]); 61 t3=dist(p,an[k]); 62 if (t1>=t2 && t1>=t3) 63 { 64 d=(p+q)/2.0; 65 r=dist(p,q)/2.0; 66 } 67 else if (t2>=t1 && t2>=t3) 68 { 69 d=(an[k]+q)/2.0; 70 r=dist(an[k],q)/2.0; 71 } 72 else 73 { 74 d=(an[k]+p)/2.0; 75 r=dist(an[k],p)/2.0; 76 } 77 } 78 } 79 } 80 void MiniDiscWithPoint(Point p,int n) 81 { 82 d=(p+an[1])/2.0; 83 r=dist(p,an[1])/2.0; 84 int j; 85 for (j=2 ;j<=n ;j++) 86 { 87 if (dist(d,an[j])<=r) continue; 88 else 89 { 90 MiniDiscWith2Point(p,an[j],j-1); 91 } 92 } 93 } 94 95 int main() 96 { 97 int n; 98 while (scanf("%d",&n)!=EOF && n) 99 { 100 for (int i=1 ;i<=n ;i++) 101 { 102 scanf("%lf%lf",&an[i].x,&an[i].y); 103 } 104 if (n==1) 105 { 106 printf("%lf %lf ",an[1].x,an[1].y); 107 continue; 108 } 109 r=dist(an[1],an[2])/2.0; 110 d=(an[1]+an[2])/2.0; 111 for (int i=3 ;i<=n ;i++) 112 { 113 if (dist(d,an[i])<=r) continue; 114 else 115 MiniDiscWithPoint(an[i],i-1); 116 } 117 printf("%.2lf %.2lf %.2lf ",d.x,d.y,r); 118 } 119 return 0; 120 }