这两题都是大同小异,一个求最小球半径,一个求球心。方法都是用模拟退火,每次往最远距离移动,并且调整步距,计数器要取值适当,掌握不好火候就会悲剧~
下面贴poj2069,codeforces 82E差不多,改一下输入输出就过
#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <string.h>
#include <deque>
#include <stack>
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <limits.h>
#include <time.h>
using namespace std;
#define LL long long
#define PI acos(-1.0)
#define N 110
#define MAX INT_MAX
#define MIN INT_MIN
#define eps 1e-8
#define FRE freopen("a.txt","r",stdin)
struct node{
double x,y,z;
}p[N];
double dis(node a,node 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));
}
int n;
int main(){
while(scanf("%d",&n) &&n){
int i,j,k;
node p0;
p0.x=0,p0.y=0,p0.z=0;
for(i=0;i<n;i++){
scanf("%lf %lf %lf",&p[i].x,&p[i].y,&p[i].z);
p0.x+=p[i].x;
p0.y+=p[i].y;
p0.z+=p[i].z;
}
p0.x/=n; //初始点为靠近中心的点
p0.y/=n;
p0.z/=n;
double step=0.1;
double s,t;
for(j=0;j<25000;j++){
k=0;
s=dis(p0,p[0]);
for(i=1;i<n;i++){
t=dis(p0,p[i]);
if(s<t){
s=t;
k=i;
}
} //往最远的点移动调整
p0.x+=(p[k].x-p0.x)*step;
p0.y+=(p[k].y-p0.y)*step;
p0.z+=(p[k].z-p0.z)*step;
step*=0.9993;
}
printf("%.5f\n",s);
}
return 0;
}