POJ 2069最小球覆盖 HDU3007最小圆覆盖【模拟淬火算法】

POJ 2069最小球覆盖

1.给定N个三维点,要求覆盖这些点的最小球半径; 2.采用模拟淬火算法,随机选取一个点作为初始解,然后不断向当前最远的点靠近; 3.这是一个不断调整的过程,对应模拟淬火算法中不断向内能最低这一目标函数(半径最小)逼近,温度对应控制变量
  • 对于一个点,球心就是这个点,且半径无穷小
  • 对于两个点,球心就是两点线段的中点,半径就是线段长度的一半
  • 对于三个点,三点构成的平面必为球的大圆,球心是三角形的外心,半径就是球心到某个点的距离
  • 对于四个点,若四点共面,则转换到3点共面;若四点不共面,四面体可以唯一确定一个外接球
  • 对于五个点及五个点以上,最小球必为某四个点的外接球
#include<iostream>
#include<map>
#include<string>
#include<cstring>
#include<vector>
#include<algorithm>
#include<set>
#include<sstream>
#include<cstdio>
#include<cmath>
#include<climits>
#include<cstdlib>
using namespace std;
const double eps=1e-3;
//POJ2069 最小球覆盖
struct POINT{
    double x,y,z;
}p[110];//N个点
POINT op;//最小球的球心
int n;
inline double dist(POINT &a,POINT &b){//两点距离
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));
}
double solve(){
    double ret,delta=100.0;//温度
    double maxDis,tempDis;
    int i,id;
    while(delta>eps){
        id=0;
        maxDis=dist(op,p[id]);
        for(i=1;i<n;i++){
            tempDis=dist(op,p[i]);
            if(tempDis>maxDis){
                maxDis=tempDis;
                id=i;
            }
        }
        ret=maxDis;
        op.x+=(p[id].x-op.x)/maxDis*delta;
        op.y+=(p[id].y-op.y)/maxDis*delta;
        op.z+=(p[id].z-op.z)/maxDis*delta;
        delta*=0.98;
    }
    return ret;//最小球半径
}
int main(){
    while(scanf("%d",&n)!=EOF&&n){
        for(int i=0;i<n;i++){
            scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].z);
        }
        printf("%lf\n", solve());
    }
    return 0;
}

HDU3007最小圆覆盖

给定N个二维点,求覆盖这些点的最小圆半径

#include<iostream>
#include<map>
#include<string>
#include<cstring>
#include<vector>
#include<algorithm>
#include<set>
#include<sstream>
#include<cstdio>
#include<cmath>
#include<climits>
#include<cstdlib>
using namespace std;
const double eps=1e-8;
//HDU3001 最小圆覆盖
struct POINT{
    double x,y,z;
}p[510];
POINT op;//最小圆的圆心
int n;
inline double dist(POINT &a,POINT &b){
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
void solve(){
    double ret,delta=100.0;
    double maxDis,tempDis;
    int i,id;
    while(delta>eps){
        id=0;
        maxDis=dist(op,p[id]);
        for(i=1;i<n;i++){
            tempDis=dist(op,p[i]);
            if(tempDis>maxDis){
                maxDis=tempDis;
                id=i;
            }
        }
        ret=maxDis;
        op.x+=(p[id].x-op.x)/maxDis*delta;
        op.y+=(p[id].y-op.y)/maxDis*delta;
        delta*=0.98;
    }
    printf("%.2lf %.2lf %.2lf\n",op.x,op.y,ret);
}
int main(){
    while(scanf("%d",&n)!=EOF){
            if(n==0)    break;
            op.x=op.y=0;
        for(int i=0;i<n;i++){
            scanf("%lf%lf",&p[i].x,&p[i].y);
            op.x+=p[i].x;
            op.y+=p[i].y;
        }
        op.x/=n;
        op.y/=n;
        solve();
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40507857/article/details/84379196