模拟退火

模拟退火是一种骗分算法。它主要适用于一些取最优值,而取值与答案找不到关系时使用。
对于这类题,我们首先需要得到一个时间复杂度并不大的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;
}
posted @ 2022-05-31 18:37  蒟蒻jht  阅读(61)  评论(0)    收藏  举报