一下来自大神博客:http://blog.sina.com.cn/s/blog_6e63f59e010120dl.html
这里介绍的算法是,先任意选取两个点,以这两个点的连线为直径作圆。再以此判断剩余的点,看它们是否都在圆内(或圆上),如果都在,说明这个圆已经找到。如果没有都在:假设我们用的最开始的两个点为p[1],p[2],并且找到的第一个不在圆内(或圆上)的点为p[i],于是我们用这个点p[i]去寻找覆盖p[1]到p[i-1]的最小覆盖圆。
那么,过确定点p[i]的从p[1]到p[i-1]的最小覆盖圆应该如何求呢?
我们先用p[1]和p[i]做圆,再从2到i-1判断是否有点不在这个圆上,如果都在,则说明已经找到覆盖1到i-1的圆。如果没有都在:假设我们找到第一个不在这个圆上的点为p[j],于是我们用两个已知点p[j]与p[i]去找覆盖1到j-1的最小覆盖圆。
而对于两个已知点p[j]与p[i]求最小覆盖圆,只要从1到j-1中,第k个点求过p[k],p[j],p[i]三个点的圆,再判断k+1到j-1是否都在圆上,若都在,说明找到圆;若有不在的,则再用新的点p[k]更新圆即可。
于是,这个问题就被转化为若干个子问题来求解了。
由于三个点确定一个圆,我们的过程大致上做的是从没有确定点,到有一个确定点,再到有两个确定点,再到有三个确定点来求圆的工作。
a.通过三个点如何求圆?
先求叉积。
若叉积为0,即三个点在同一直线,那么找到距离最远的一对点,以它们的连线为直径做圆即可;
若叉积不为0,即三个点不共线,那么就是第二个问题,如何求三角形的外接圆?
b.如何求三角形外接圆?
假设三个点(x1,y1),(x2,y2),(x3,y3);
设过(x1,y1),(x2,y2)的直线l1方程为Ax+By=C,它的中点为(midx,midy)=((x1+x2)/2,(y1+y2)/2),l1中垂线方程为A1x+B1y=C1;则它的中垂线方程中A1=-B=x2-x1,B1=A=y2-y1,C1=-B*midx+A*midy=((x2^2-x1^2)+(y2^2-y1^2))/2;
同理可以知道过(x1,y1),(x3,y3)的直线的中垂线的方程。
于是这两条中垂线的交点就是圆心。
c.如何求两条直线交点?
设两条直线为A1x+B1y=C1和A2x+B2y=C2。
设一个变量det=A1*B2-A2*B1;
如果det=0,说明两直线平行;若不等于0,则求交点:x=(B2*C1 -B1*C2)/det,y=(A1*C2-A2*C1)/det;
d.于是木有了。。
http://oj.jxust.edu.cn/problem.php?id=1328
大牛代码:
1 #include<stdio.h> 2 #include<math.h> 3 struct TPoint{ 4 double x,y; 5 }; 6 TPoint a[1005],d; 7 double r; 8 9 double distance(TPoint p1, TPoint p2){ 10 return (sqrt((p1.x-p2.x)*(p1.x -p2.x)+(p1.y-p2.y)*(p1.y-p2.y))); 11 } 12 double multiply(TPoint p1, TPoint p2, TPoint p0) { 13 return ((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y)); 14 } 15 void MiniDiscWith2Point(TPoint p,TPoint q,int n){ 16 d.x=(p.x+q.x)/2.0; 17 d.y=(p.y+q.y)/2.0; 18 r=distance(p,q)/2; 19 int k; 20 double c1,c2,t1,t2,t3; 21 for(k=1;k<=n;k++){ 22 if(distance(d,a[k])<=r)continue; 23 if(multiply(p,q,a[k])!=0.0){ 24 c1=(p.x*p.x+p.y*p.y-q.x*q.x-q.y*q.y)/2.0; 25 c2=(p.x*p.x+p.y*p.y-a[k].x*a[k].x-a[k].y*a[k].y)/2.0; 26 d.x=(c1*(p.y-a[k].y)-c2*(p.y-q.y))/((p.x-q.x)*(p.y-a[k].y)-(p.x-a[k].x)*(p.y-q.y)); 27 d.y=(c1*(p.x-a[k].x)-c2*(p.x-q.x))/((p.y-q.y)*(p.x-a[k].x)-(p.y-a[k].y)*(p.x-q.x)); 28 r=distance(d,a[k]); 29 } 30 else{ 31 t1=distance(p,q); 32 t2=distance(q,a[k]); 33 t3=distance(p,a[k]); 34 if(t1>=t2&&t1>=t3) 35 {d.x=(p.x+q.x)/2.0;d.y=(p.y+q.y)/2.0;r=distance(p,q)/2.0;} 36 else if(t2>=t1&&t2>=t3) 37 {d.x=(a[k].x+q.x)/2.0;d.y=(a[k].y+q.y)/2.0;r=distance(a[k],q)/2.0;} 38 else 39 {d.x=(a[k].x+p.x)/2.0;d.y=(a[k].y+p.y)/2.0;r=distance(a[k],p)/2.0;} 40 } 41 } 42 } 43 44 void MiniDiscWithPoint(TPoint pi,int n){ 45 d.x=(pi.x+a[1].x)/2.0; 46 d.y=(pi.y+a[1].y)/2.0; 47 r=distance(pi,a[1])/2.0; 48 int j; 49 for(j=2;j<=n;j++){ 50 if(distance(d,a[j])<=r)continue; 51 else{ 52 MiniDiscWith2Point(pi,a[j],j-1); 53 } 54 } 55 } 56 int main(){ 57 int i,n, t; 58 scanf("%d ", &t); 59 while(t--){ 60 scanf("%d",&n); 61 for(i=1;i<=n;i++){ 62 scanf("%lf %lf",&a[i].x,&a[i].y); 63 } 64 if(n==1) 65 { printf("%.1lf %.1lf ",a[1].x,a[1].y);continue;} 66 r=distance(a[1],a[2])/2.0; 67 d.x=(a[1].x+a[2].x)/2.0; 68 d.y=(a[1].y+a[2].y)/2.0; 69 for(i=3;i<=n;i++){ 70 if(distance(d,a[i])<=r)continue; 71 else 72 MiniDiscWithPoint(a[i],i-1); 73 } 74 printf("%.1lf %.1lf ",d.x,d.y); 75 } 76 return 0; 77 }
垃圾代码:
1 #include <iostream> 2 #include <stdio.h> 3 #include <cmath> 4 using namespace std; 5 double r; 6 struct Node { 7 double x, y; 8 } T[1005], t; 9 double dis(Node a, Node b){ 10 return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y)); 11 } 12 double xmup(Node a, Node b, Node c){ 13 return (a.x - b.x)*(a.y - c.y) - (a.y - b.y)*(a.x - c.x); 14 } 15 void FindMin2(Node a, Node b, int x){ 16 t.x = (a.x + b.x) /2.0; 17 t.y = (a.y + b.y) /2.0; 18 r = dis(a, b) /2.0; 19 for(int i = 1; i < x; i++){ 20 if(dis(t, T[i]) <= r) continue; 21 if(xmup(a, b, T[i]) == 0.0){ 22 t.x = (a.x + b.x + T[i].x) /3.0; 23 t.y = (a.y + b.y + T[i].y) /3.0; 24 r = dis(t, T[i]); 25 }else{ 26 double a1 = 2.0*(a.x - b.x), a2 = 2.0*(a.x - T[i].x); 27 double b1 = 2.0*(a.y - b.y), b2 = 2.0*(a.y - T[i].y); 28 double c1 = a.x*a.x + a.y*a.y - b.x*b.x - b.y*b.y; 29 double c2 = a.x*a.x + a.y*a.y - T[i].x*T[i].x - T[i].y*T[i].y; 30 t.x = (c1*b2 - c2*b1) / (a1*b2 - b1*a2); 31 t.y = (a1*c2 - a2*c1) / (a1*b2 - b1*a2); 32 r = dis(t, T[i]); 33 } 34 } 35 } 36 void FindMin(Node a, int x){ 37 t.x = (a.x + T[1].x) /2.0; 38 t.y = (a.y + T[1].y) /2.0; 39 r = dis(a, T[1]) /2.0; 40 for(int i = 2; i < x; i++){ 41 if(dis(t, T[i]) <= r) continue; 42 FindMin2(a, T[i], i); 43 } 44 } 45 int main(){ 46 int n, m; 47 scanf("%d", &n); 48 while(n--){ 49 scanf("%d", &m); 50 for(int i = 1; i <= m; i++){ 51 scanf("%lf %lf", &T[i].x, &T[i].y); 52 } 53 if(m == 1){ 54 printf("%.1lf %.1lf ", T[1].x, T[1].y); 55 continue; 56 } 57 t.x = (T[1].x + T[2].x) /2.0; 58 t.y = (T[1].y + T[2].y) /2.0; 59 r = dis(T[1], T[2]) /2.0; 60 for(int i = 3; i <= m; i++){ 61 if(dis(t, T[i]) <= r) continue; 62 FindMin(T[i], i); 63 } 64 printf("%.1lf %.1lf ", t.x, t.y); 65 } 66 return 0; 67 }
http://acm.hdu.edu.cn/showproblem.php?pid=3007
1 #include <cmath> 2 #include <stdio.h> 3 #include <iostream> 4 using namespace std; 5 double r; 6 struct Node{ 7 double x, y; 8 }T[505], t; 9 double dis(Node a, Node b){ 10 return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y-b.y)); 11 } 12 double xmup(Node a, Node b, Node c){ 13 return (a.x - b.x)*(c.y - b.y) - (a.y - b.y)*(c.x - b.x); 14 } 15 void FindMin2(Node a, Node b, int x){ 16 t.x = (a.x + b.x) /2.0; 17 t.y = (a.y + b.y) /2.0; 18 r = dis(a, b) /2.0; 19 for(int i = 1; i < x; i++){ 20 if(dis(t, T[i]) <= r) continue; 21 if(xmup(a, b, T[i]) == 0.0) { 22 t.x = (a.x + b.x + T[i].x) /3.0; 23 t.y = (a.y + b.y + T[i].y) /3.0; 24 r = dis(t, T[i]); 25 }else{ 26 double a1 = 2.0*(a.x - b.x), a2 = 2.0*(a.x - T[i].x); 27 double b1 = 2.0*(a.y - b.y), b2 = 2.0*(a.y - T[i].y); 28 double c1 = a.x*a.x + a.y*a.y - b.x*b.x - b.y*b.y; 29 double c2 = a.x*a.x + a.y*a.y - T[i].x*T[i].x - T[i].y*T[i].y; 30 t.x = (c1*b2 - c2*b1) / (a1*b2 - b1*a2); 31 t.y = (a1*c2 - a2*c1) / (a1*b2 - b1*a2); 32 r = dis(t, T[i]); 33 } 34 } 35 } 36 void FindMin(Node a, int x){ 37 t.x = (T[1].x + a.x) /2.0; 38 t.y = (T[1].y + a.y) /2.0; 39 r = dis(T[1], a) /2.0; 40 for(int i = 2; i < x; i++){ 41 if(dis(t, T[i]) <= r) continue; 42 else FindMin2(a, T[i], i); 43 } 44 } 45 int main(){ 46 int n; 47 while(scanf("%d", &n)){ 48 if(n == 0) break; 49 for(int i = 1; i <= n; i++){ 50 scanf("%lf %lf", &T[i].x, &T[i].y); 51 } 52 if(n == 1){ 53 printf("wenbaozuishuai"); 54 continue; 55 } 56 t.x = (T[1].x + T[2].x) /2.0; 57 t.y = (T[1].y + T[2].y) /2.0; 58 r = dis(T[1], T[2]) /2.0; 59 for(int i = 3; i <= n; i++){ 60 if(dis(t, T[i]) <= r) continue; 61 FindMin(T[i], i); 62 } 63 printf("%.2lf %.2lf %.2lf ", t.x, t.y, r); 64 } 65 return 0; 66 }
只有不断学习才能进步!