本人水平有限,题解不到为处,请多多谅解
本蒟蒻谢谢大家观看
题目:传送门
大致的模拟退火讲解我这里不再赘述,如有疑问请看这里
code:
#include <bits/stdc++.h>
#define down 0.996//徐徐降温
using namespace std;
int n;
struct node{
int x;
int y;
int w;
}object[2005];//存下物体的坐标
double ansx,ansy,answ;//最终答案
double energy(double x,double y)//根据物理学知识,能量总和越小越稳定
{
double r=0,dx,dy;
for (int a=1;a<=n;a++)
{
dx=x-object[a].x;
dy=y-object[a].y;
r+=sqrt(dx*dx+dy*dy)*object[a].w;
}
return r;
}
void sa()//模拟退火
{
double t=3000;//温度要足够高
while (t>1e-15)//略大于0
{
//生成[-T*RAND_MAX,T*RAND_MAX)的随机变动范围(rand():[0,RAND_MAX))
//rand()一个随机数,RAND_MAX随机范围内最大值
double ex=ansx+(rand()*2-RAND_MAX)*t;//随机产生新的答案
double ey=ansy+(rand()*2-RAND_MAX)*t;
double ew=energy(ex,ey);
double de=ew-answ;
if (de<0)//如果此答案更优,就接受
{
ansx=ex;
ansy=ey;
answ=ew;
}
else if(exp(-de/t)*RAND_MAX>rand())
//以概率exp(-Δt′/T)接受S′作为新的当前解S。
//否则根据多项式概率接受
{
ansx=ex;
ansy=ey;
}
t*=down;
}
}
void solve()//多跑几遍退火,增加得到最优解的概率
{
sa();
sa();
sa();
sa();
}
int main()
{
cin>>n;
for (int a=1;a<=n;a++)
{
scanf("%d%d%d",&object[a].x,&object[a].y,&object[a].w);
ansx+=object[a].x;
ansy+=object[a].y;
}
ansx/=n;//以平均数作为初始答案
ansy/=n;
answ=energy(ansx,ansy);
solve();
printf("%.3lf %.3lf\n",ansx,ansy);//华丽的输出
return 0;
}