数论-模拟退火

题目
大佬说这题可以很好的入门模拟退火
虽然模拟退火不是这题的最佳解
但是确实可以通过这个来理解模拟退火的思想
本题求一个平衡点,我们要找一个点使得∑ni=di∗wi最小(di为i点到该点的距离)。

#include
#include
#include
#include
#define RG register
#define R RG long double
#define RD T*(rand()*2-RAND_MAX)

const int maxn=1009;
const long double D=0.97,EPS=1e-14;//参数。。。模拟退火的核心(但是不会调-_-)
double x[maxn],y[maxn],w[maxn];
int n;

inline long double calc(R x0,R y0)//计算当前选定点的势能
{
	R res=0,dx,dy;
	for(RG int i=1;i<=n;++i){
		dx=x[i]-x0;
		dy=y[i]-y0;
		res+=sqrt(dx*dx+dy*dy)*w[i];
	}
	return res;
}

int main()
{
	R T,x0,y0,x1,y1,res,ans,best,bx=0,by=0;
	RG int i,times=1;
	scanf("%d",&n);
	for(i=1;i<=n;++i) { 
		scanf("%lf%lf%lf",&x[i],&y[i],&w[i]);
		bx+=x[i];
		by+=y[i];
	}
	best=ans=calc(bx/=n,by/=n);
	srand(time(NULL));//保证每次的随机数不一样
	while(times--) {
		ans=best;
		x0=bx;y0=by;
		for(T=100000;T>EPS;T*=D)
		{
			x1=x0+RD;y1=y0+RD;
			res=calc(x1,y1);
			if(best>res) {
				best=res;
				bx=x1;
				by=y1;
			}
			if(ans>res||exp((ans-res)/T)>(long double)rand()/RAND_MAX) {
			//rand()/RAND_MAX,随机生成一个小于1的数,
			//至于这个exp((ans-res)/T)是科学家计算出来的,我们用就好了
				ans=res;
				x0=x1;
				y0=y1;
			}
		}
	}
	printf("%.3Lf %.3Lf\n",bx,by);//输出用Lf
    return 0;
}



你可能感兴趣的:(数论)