题目链接
题目大意:给定n个质点,求重心–广义费马点
题解:模拟退火,爬山也可以
我的收获:get搜索姿势
#include
#include
#include
#include
#define N 10005
using namespace std;
int n,i;
double ansx,ansy,nowx,nowy,nx,ny,dis;
double T,now,x[N],y[N],w[N];
double Rand(){return (double)(rand()%20000)/20000.0;}
double dist(double xx,double yy){
now=0;
for(int i=1;i<=n;i++)now+=sqrt((xx-x[i])*(xx-x[i])+(yy-y[i])*(yy-y[i]))*w[i];
if(nowreturn now;
}
void SA()
{
while(T>0.001){
nx=nowx;ny=nowy;
nx=nx+T*(Rand()*2-1);
ny=ny+T*(Rand()*2-1);//在当前位置的变化幅度内随机取一点
now=dist(nowx,nowy)-dist(nx,ny);//计算当前解
if(now>0||exp(now/T)>rand()){//如果当前解比最优解好那么取为当前解,否则以exp|当前解-最优解|/T的概率接受当前解
nowx=nx;
nowy=ny;
}
T*=0.98;//降低搜索范围(降温)
}
for (int i=1;i<=1000;i++)//为了使答案尽量优,再以这个求出的坐标为基准向四周随机移动若干次,取最优解。
{
nx=ansx+T*(Rand()*2-1);
ny=ansy+T*(Rand()*2-1);
dist(nx,ny);
}
}
void work()
{
ansx/=(double)n;ansy/=(double)n;T=100000;//变化幅度
nowx=ansx=nowy=ansy;//初始位置
dis=dist(ansx,ansy);//当前最优解
SA();
printf("%.3lf %.3lf",ansx,ansy);
}
void init()
{
srand(247978423);//bzoj不能用time(0)……
cin>>n;
for(i=1;i<=n;i++)
scanf("%lf%lf%lf",&x[i],&y[i],&w[i]),ansx+=x[i],ansy+=y[i];
}
int main()
{
init();
work();
return 0;
}