P1337 [JSOI2004]平衡点 / 吊打XXX

题目链接

题意分析

这道题正解是啥我不清楚 我只是来联系一下模拟退火

关于模拟退火要注意的几点

1.初始温度\(T\) 以及每一次降温的比例\(ΔT\)

2.如果当前可以取代最优解的话 就取代

否则的话 就按照多项式复杂度\(e^{\frac{Δf}{T}}\)\(\frac{rand()}{RAND_MAX}\)比较 大于的话 我们就修改

因为这样可以防止我们执着于较优解而忽略了最优解

3.退火的总次数 当然是越多越好了

CODE:

#include<bits/stdc++.h>
#define eps 1e-3
#define N 2010
using namespace std;
int n;
double ansx,ansy,answ;
const double down=0.995;
struct Node
{
	double x,y,w;
}e[N];
double getdis(double ax,double ay,double bx,double by)
{return sqrt((ax-bx)*(ax-bx)+(ay-by)*(ay-by));}
double getans(double x,double y)
{
	double tmp=0;
	for(int i=1;i<=n;++i) tmp+=getdis(x,y,e[i].x,e[i].y)*e[i].w;
	return tmp;
}
void SA()
{
	double T=3000;
	double nowx=ansx,nowy=ansy,noww=answ;
	while(T>1e-15)
	{
		double tx=nowx+(rand()*2-RAND_MAX)*T;
		double ty=nowy+(rand()*2-RAND_MAX)*T;
		double tw=getans(tx,ty);
		if(tw<answ) ansx=tx,ansy=ty,answ=tw;
		if(tw<noww||exp((noww-tw)/T)*RAND_MAX>rand())
		{
			nowx=tx;nowy=ty;noww=tw;
		}
		T*=down;
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;++i) 
	{
		scanf("%lf%lf%lf",&e[i].x,&e[i].y,&e[i].w);
		ansx+=e[i].x;ansy+=e[i].y;
	}
	ansx/=n;ansy/=n;answ=getans(ansx,ansy);
	SA();SA();SA();SA();
	printf("%.3lf %.3lf\n",ansx,ansy);
	return 0;
}
原文地址:https://www.cnblogs.com/tcswuzb/p/14363668.html