包含點集所有點的最小圓的算法最小圓覆蓋 http://acm.zju.edu.cn/show_problem.php?pid=1450 相關題目最小球包含 http://acm.pku.edu.cn/JudgeOnline/problem?id=2069 平面上有n個點,給定n個點的坐標,試找一個半徑最小的圓,將n 個點全部包圍,點可以在圓上。 1. 在點集中任取3點A,B,C。 2. 作一個包含A,B,C三點的最小圓,圓周可能通過這3點,也可能只通過其中兩點,但包含第3點.后一種情況圓周上的兩點一定是位于圓的一條直徑的兩端。 3. 在點集中找出距離第2步所建圓圓心最遠的D點,若D點已在圓內或圓周上,則該圓即為所求的圓,算法結束.則,執行第4步。 4. 在A,B,C,D中選3個點,使由它們生成的一個包含這4個點的圓為最小,這3 點成為新的A,B,C,返回執行第2步。若在第4步生成的圓的圓周只通過A,B,C,D 中的兩點,則圓周上的兩點取成新的A和B,從另兩點中任取一點作為新的C。 程序設計題解上的解題報告:對于一個給定的點集A,記MinCircle(A)為點集A的最小外接圓,顯然,對于所有的點集情況A,MinCircle(A)都是存在且惟一的。需要特別說明的是,當A為空集時,MinCircle(A)為空集,當A={a}時,MinCircle(A)圓心坐標為a,半徑為0; 顯然,MinCircle(A)可以有A邊界上最多三個點確定(當點集A中點的個數大于 1時,有可能兩個點確定了MinCircle(A)),也就是說存在著一個點集B,|B|<=3 且B包含與A,有MinCircle(B)=MinCircle(A).所以,如果a不屬于B,則 MinCircle(A-{a})=MinCircle(A);如果MinCircle(A-{a})不等于MinCircle(A),則 a屬于B。 所以我們可以從一個空集R開始,不斷的把題目中給定的點集中的點加入R,同時維護R的外接圓最小,這樣就可以得到解決該題的算法。
zju 1450
題目描述:給定n個點,求覆蓋所有點的圓的圓心和半徑
#include<stdio.h>
#include
<math.h>
#include
<string.h>
#define MAXN 20
struct pointset{
    
double x, y;
};
const double precison=1.0e-8;
pointset maxcic, point[MAXN];
double radius;
int curset[MAXN], posset[3];
int set_cnt, pos_cnt;
inline 
double dis_2(pointset &from, pointset& to){
    
return ((from.x-to.x)*(from.x-to.x)+(from.y-to.y)*(from.y-to.y));
}
int in_cic(int pt){
    
if(sqrt(dis_2(maxcic, point[pt]))<radius+precison) return 1;
    
return 0;
}
int cal_mincic(){
    
if(pos_cnt==1 || pos_cnt==0)
        
return 0;
    
else if(pos_cnt==3){
        
double A1, B1, C1, A2, B2, C2;
        
int t0=posset[0], t1=posset[1], t2=posset[2];
        A1
=2*(point[t1].x-point[t0].x);
        B1
=2*(point[t1].y-point[t0].y);
        C1
=point[t1].x*point[t1].x-point[t0].x*point[t0].x+
            point[t1].y
*point[t1].y-point[t0].y*point[t0].y;
        A2
=2*(point[t2].x-point[t0].x);
        B2
=2*(point[t2].y-point[t0].y);
        C2
=point[t2].x*point[t2].x-point[t0].x*point[t0].x+
            point[t2].y
*point[t2].y-point[t0].y*point[t0].y;
        maxcic.y
=(C1*A2-C2*A1)/(A2*B1-A1*B2);
        maxcic.x
=(C1*B2-C2*B1)/(A1*B2-A2*B1);
        radius
=sqrt(dis_2(maxcic, point[t0]));
    }
    
else if(pos_cnt==2){
        maxcic.x
=(point[posset[0]].x+point[posset[1]].x)/2;
        maxcic.y
=(point[posset[0]].y+point[posset[1]].y)/2;
        radius
=sqrt(dis_2(point[posset[0]], point[posset[1]]))/2;
    }
    
return 1;
}
int mindisk(){
    
if(set_cnt==0 || pos_cnt==3){
        
return cal_mincic();
    }
    
int tt=curset[--set_cnt];
    
int res=mindisk();
    set_cnt
++;
    
if(!res || !in_cic(tt)){
        set_cnt
--;
        posset[pos_cnt
++]=curset[set_cnt];
        res
=mindisk();
        pos_cnt
--;
        curset[set_cnt
++]=curset[0];
        curset[
0]=tt;
    }
    
return res;
}
int main(){
    freopen(
"in2.txt""r", stdin);
    freopen(
"radius.txt""w", stdout);
    
int n;
    
while(scanf("%d"&n)!=EOF){
        
if(n==0break;
        
int i;
        
for(i=0; i<n; i++)
            scanf(
"%lf %lf"&point[i].x, &point[i].y);
            
if(n==1){
                maxcic.x
=point[0].x;
                maxcic.y
=point[0].y;
                radius
=0;
                printf(
"%.2lf %.2lf %.2lf\n", maxcic.x, maxcic.y, radius);
                
continue;
            }
            set_cnt
=n; pos_cnt=0;
            
for(i=0 ;i<n ;i++)  curset[i]=i;
            mindisk();
            printf(
"%.2lf %.2lf %.2lf\n", maxcic.x, maxcic.y, radius);
    }

    
return 0;
}