題意:給出n個點的座標,求一個最小球的半徑,使其能覆蓋所有的點。
分析:這個題跟poj-2069是一樣的,把那道題搞懂這個題也就懂了。這個題用模擬退火做的話唯一麻煩的是調試參數......QAQ
真的賊麻煩....
代碼如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=200;
struct Node{
double x,y,z;
}p[maxn];
Node ans;
double avex,avey,avez;
const double eps=1e-8;
int 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));
}
void SA(){
double T=10050;
double ret=1e30;
while(T>eps){
int id=1;
double max_dis=dis(ans,p[1]);
for(int i=2;i<=N;i++){
double tem=dis(ans,p[i]);
if(tem>max_dis){
max_dis=tem;
id=i;
}
}
ret=min(ret,max_dis);
ans.x+=(p[id].x-ans.x)*T/max_dis;
ans.y+=(p[id].y-ans.y)/max_dis*T;
ans.z+=(p[id].z-ans.z)/max_dis*T;
T*=0.98;
}
printf("%.15f\n",ret);
}
int main()
{
scanf("%d",&N);
for(int i=1;i<=N;i++){
scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].z);
avex+=p[i].x;avey+=p[i].y;avez+=p[i].z;
}
avex/=N;avey/=N;avez/=N;
ans.x=avex;ans.y=avey;ans.z=avez;
SA();
return 0;
}
<附>我在調試的時候還遇到了一個玄學的bug。。。
如果找最優解取min是這樣寫的:
ret=min(max_dis,ret);
會神奇的WA3.... QAQ....