【模拟退火】poj2069 Super Star

题意:让你求空间内n个点的最小覆盖球。

模拟退火随机走的时候主要有这几种走法:①随机旋转角度。

②直接不随机,往最远的点的方向走,仅仅在尝试接受解的时候用概率。(最小圆/球覆盖时常用)

③往所有点的方向的总和走,仅仅在尝试接受解的时候用概率。(费马点时常用)

像这题,我用第一种最暴力的随机,死活过不了……

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstdlib>
using namespace std;
const double EPS=0.00000001;
const double PI=acos(-1.0);
struct Point{
	double x,y,z;
	Point(const double &x,const double &y,const double &z){
		this->x=x;
		this->y=y;
		this->z=z;
	}
	Point(){}
	void read(){
		scanf("%lf%lf%lf",&x,&y,&z);
	}
	double length(){
		return sqrt(x*x+y*y+z*z);
	}
}a[35],p,allp;
double ans,allans;
int n;
typedef Point Vector;
Vector operator - (const Point &a,const Point &b){
	return Vector(a.x-b.x,a.y-b.y,a.z-b.z);
}
Vector operator + (const Vector &a,const Vector &b){
	return Vector(a.x+b.x,a.y+b.y,a.z+b.z);
}
Vector operator * (const double &K,const Vector &v){
	return Vector(K*v.x,K*v.y,K*v.z);
}
double calc(Point p){
	double res=0.0;
	for(int i=1;i<=n;++i){
		res=max(res,(a[i]-p).length());
	}
	return res;
}
//double ran(){
//	int fm=rand()%10000+1;
//	return ((rand()&1) ? -1.0 : 1.0)*((double)(rand()%(fm+1))/(double)fm);
//}
Vector unit(Vector v){
	double l=v.length();
	return Vector(v.x/l,v.y/l,v.z/l);
}
int main(){
	srand(233);
	//freopen("poj2069.in","r",stdin);
	while(1){
		scanf("%d",&n);
		if(!n){
			return 0;
		}
		allans=100000.0;
		for(int i=1;i<=n;++i){
			a[i].read();
		}
//		for(int j=1;j<=n;++j){
			p=a[1];
			ans=calc(p);
			double T=sqrt(20000.0);
			while(T>EPS){
				double bestnow=100000.0;
				Point besttp;
//				for(int i=1;i<=30;++i){
//					double rad=(double)(rand()%10000+1)/10000.0*2.0*PI;
					int to;
					double far=0.0;
					for(int k=1;k<=n;++k){
						double tmp=(a[k]-p).length();
						if(tmp>far){
							far=tmp;
							to=k;
						}
					}
					Point tp=p+T*unit(a[to]-p);
					double now=calc(tp);
					if(now<bestnow){
						bestnow=now;
						besttp=tp;
					}
//				}
				if(bestnow-100000.0<-EPS && (bestnow<ans || exp((ans-bestnow)/T)*10000.0>(double)(rand()%10000))){
					ans=bestnow;
					p=besttp;
				}
				T*=0.99;
			}
			if(ans<allans){
				allans=ans;
//				allp=p;
			}
//		}
		printf("%.5lf
",fabs(allans));
	}
	return 0;
}
原文地址:https://www.cnblogs.com/autsky-jadek/p/7528342.html