题目:http://poj.org/problem?id=2069
仍是随机地模拟退火,然而却WA了;
看看网上的题解,都是另一种做法——向距离最远的点靠近;
于是也改成那样,竟然真的A了...感觉这个做法的随机因素好像很小?不过似乎也是一种套路。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> #include<ctime> #define eps 1e-17 #define dt 0.997 using namespace std; typedef double db; int const xn=35; int n; db xx[xn],yy[xn],zz[xn],ans,ansx,ansy,ansz; int rd() { int ret=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();} while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar(); return f?ret:-ret; } db dist(db x,db y,db z,db a,db b,db c){return sqrt((x-a)*(x-a)+(y-b)*(y-b)+(z-c)*(z-c));} db cal(db x,db y,db z) { db ret=0; for(int i=1;i<=n;i++)ret=max(ret,dist(x,y,z,xx[i],yy[i],zz[i])); return ret; } void SA() { db T=10000,x=ansx,y=ansy,z=ansz,lst=ans,tx,ty,tz,tmp; while(T>eps) { int id; db ret=0,tt; for(int i=1;i<=n;i++) if((tt=dist(x,y,z,xx[i],yy[i],zz[i]))>ret)ret=tt,id=i; ans=min(ans,ret); x+=(xx[id]-x)/ret*T; y+=(yy[id]-y)/ret*T; z+=(zz[id]-z)/ret*T; T*=dt; } } int main() { srand(time(0)); while(1) { n=rd(); if(!n)return 0; db sx=0,sy=0,sz=0; for(int i=1;i<=n;i++) scanf("%lf%lf%lf",&xx[i],&yy[i],&zz[i]),sx+=xx[i],sy+=yy[i],sz+=zz[i]; ansx=sx/n; ansy=sy/n; ansz=sz/n; ans=cal(ansx,ansy,ansz); SA(); printf("%.5lf\n",ans); } return 0; }