题意为求点的最小外接球。 本想随机模拟退火,可是怎么也掌握不好火候。 后来改为每次定向变步长,取的点向离它最远的那个点移动。 初始随机了10个点。
POJ 2069 #include<iostream> #include<time.h> #include<cmath> #define sqr(x) (x)*(x) #define FOR(i,a,b) for(int i=a;i<b;i++) #define FF(i,a) for(int i=0;i<a;i++) using namespace std; const double eps=1e-6; const double INF=1e20; const double pi=acos(-1.0); struct Houxuan { double x,y,z,dist; }pp[10]; struct PT { double x,y,z; }hole[30]; double dis(double x1,double y1,double z1,double x2,double y2,double z2) { return sqrt(sqr(x1-x2)+sqr(y1-y2)+sqr(z1-z2)); } int n; int main() { int P=10; while(scanf("%d",&n)&&n) { double delta=100.0; FF(i,n) scanf("%lf%lf%lf",&hole[i].x,&hole[i].y,&hole[i].z); FF(i,P) { pp[i].x=double(rand()%10000+1)/10000.0*100; pp[i].y=double(rand()%10000+1)/10000.0*100; pp[i].z=double(rand()%10000+1)/10000.0*100; pp[i].dist=0; FF(j,n) pp[i].dist=max(pp[i].dist,dis(pp[i].x,pp[i].y,pp[i].z,hole[j].x,hole[j].y,hole[j].z)); } while(delta>eps) { FF(i,P) { int idx=0; double tmp=0; FF(j,n) { double d=dis(hole[j].x,hole[j].y,hole[j].z,pp[i].x,pp[i].y,pp[i].z); if(d>tmp) { idx=j; tmp=d; } } pp[i].dist=min(pp[i].dist,tmp); pp[i].x=pp[i].x+(hole[idx].x-pp[i].x)/tmp*delta; pp[i].y=pp[i].y+(hole[idx].y-pp[i].y)/tmp*delta; pp[i].z=pp[i].z+(hole[idx].z-pp[i].z)/tmp*delta; } delta*=0.98; } int idx=0; FOR(i,1,P) { if(pp[i].dist<pp[idx].dist) idx=i; } printf("%.5lf\n",pp[idx].dist); } return 0; }
|