1.我提交该题解100%ac,但是这是因为该题解没有加随机种子,加上就会使分数在60-100之间跳动 2.模拟退火应当设置一个全局最优解在每次sa后更新一次,如题解的做法,退火多次意义会变小,容易丢失最优解,我加上全局最优解后几乎可以做到全部ac
最后,如果该题解真的有问题,请求管理员撤下,否则会误导学习模拟退火的同学
附代码:
#include <bits/stdc++.h>
using namespace std;
//mt19937 myrand(time(0));
int n;
double globalx, globaly, globalenergy;
int xx[100000], yy[100000], w[100000];
double energy(double x, double y) {
double r = 0;
for(int i = 1; i <= n; ++i) {
double dx = x - xx[i], dy = y - yy[i];
r += sqrt(dx * dx + dy * dy) * w[i];
}
return r;
}
double ansx, ansy, answ;
void sa() {
double t = 3000;
while(t > 1e-15) {
double ex = ansx + (rand() * 2 - RAND_MAX) * t;
double ey = ansy + (rand() * 2 - RAND_MAX) * t;
auto ew = energy(ex, ey);
auto de = ew - answ;
if(de < 0) {
answ = ew;
ansx = ex;
ansy = ey;
} else if(exp(-de / t) * RAND_MAX > rand()) {
ansx = ex;
ansy = ey;
}
t *= 0.996;
}
}
int main() {
// srand((unsigned)time(0));
scanf("%d", &n);
for(int i = 1; i <= n; ++i) {
scanf("%d %d %d", &xx[i], &yy[i], &w[i]);
ansx += xx[i];
ansy += yy[i];
}
ansx /= n;
ansy /= n;
globalx = ansx;
globaly = ansy;
globalenergy = answ = energy(ansx, ansy);
for(int i = 1; i <=4; ++i) {
sa();
if(answ < globalenergy) {
globalx = ansx;
globaly = ansy;
globalenergy = answ;
}
}
printf("%.3lf %.3lf", globalx, globaly);
return 0;
}