模拟退火
模拟退火是一种骗分算法。它主要适用于一些取最优值,而取值与答案找不到关系时使用。
对于这类题,我们首先需要得到一个时间复杂度并不大的calc函数,表示对于某一个取值时的答案。
接着就是退火函数
点击查看代码
void tuihuo(){
double cur=rand(-10000,10000);
for(double t=1e4;t>1e-15;t*=0.999){
pdd nw=rand(cur-t,cur+t);
double dt=calc(nw)-calc(cur);
if(exp(-dt/t)>rand(0,1)) cur=nw;
}
}
#include<bits/stdc++.h>
#define pdd pair<double ,double>
#define x first
#define y second
#define M 1005
using namespace std;
int n;
pdd anss;
double x[M],y[M],z[M],ans=-1;
double rand(double qwe,double ewq){
return (double)rand()/RAND_MAX*(ewq-qwe)+qwe;
}
double dist(pdd a,int qwe){
double dx=a.x-x[qwe];
double dy=a.y-y[qwe];
return sqrt(dx*dx+dy*dy);
}
double calc(pdd qwe){
double res=0;
for(int i=1;i<=n;++i){
res+=dist(qwe,i)*z[i];
}
if(ans>res||ans==-1) ans=res,anss=qwe;
return res;
}
void tuihuo(){
pdd cur(rand(-10000,10000),rand(-10000,10000));
for(double t=1e4;t>1e-15;t*=0.999){
pdd nw(rand(cur.x-t,cur.x+t),rand(cur.y-t,cur.y+t));
double dt=calc(nw)-calc(cur);
if(exp(-dt/t)>rand(0,1)) cur=nw;
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%lf%lf%lf",&x[i],&y[i],&z[i]);
for(int i=0;i<2;++i) tuihuo();
printf("%.3lf %.3lf",anss.x,anss.y);
return 0;
}