模拟退火学习笔记

模拟退火学习笔记

膜你颓祸

退火

在每个温度都有几率跳到一个劣与当前的位置,温度越低,劣解的采纳率更低

因为在每个温度都有足够的时间来找到合适的位置,所以最后答案接近正确

模拟退火

就是在解决一类问题中模拟上述方法

形式化地,对于当前一个新解\(f(x)\),有

  1. \(f(x')>f(x)\),取此解
  2. \(f(x')<f(x)\),以一定的概率取此解

优缺点

优点:适用性强

缺点:能否AC看运气(概率问题),仅限于偏分使用(需要卡时

伪代码

void sa(){
    double t=200.0;
    while(t>eps){
    	for (情况总数){
        	newAns=使用这种情况下的答案
        	delta=f(newans)-f(nowans)(f:估价) 
        	if( delta满足条件 || ( exp(-delta/t)*RAND_MAX>rand() ) { nowans=newans; }
    	}
    	t*=decTemp;
    }
}

吊打LCY(模板)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<algorithm>
#include<cstdlib>
#include<cmath>
using namespace std;
#define db double
int n;
const int N = 1001;
double x[N],y[N],w[N];
double ansx,ansy;
const db eps=1e-18;
int cnt=0;
inline int read(){
	int x=0,pos=1;char ch=getchar();
	for(;!isdigit(ch);ch=getchar()) if(ch=='-' ) pos=0;
	for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
	return pos?x:-x;
}
double f(double nx,double ny){
	double tot=0;
	for(int i=1;i<=n;i++){
		tot+=w[i]*(db)sqrt((nx-(x[i]))*(nx-(x[i]))+(ny-y[i])*(ny-y[i]));
	}
	return tot;
}
void sa(){
	double t=200;
	while(t>eps){
		double nowx=ansx+(rand()*2-RAND_MAX)*t,nowy=ansy+(rand()*2-RAND_MAX)*t;
		double delta=f(nowx,nowy)-f(ansx,ansy);
		if(delta<0||(exp(-delta/t)*((db)(RAND_MAX))>((db)(rand())))){ansx=nowx,ansy=nowy;} //exp(-x)在x越小越接近1,即温度越大或者与当前最优解越接近取此答案 
		t*=0.998; 
	}
}
int main(){
	srand(time(0)+19260817);
	n=read();
	for(int i=1;i<=n;i++){
		scanf("%lf%lf%lf",&x[i],&y[i],&w[i]);
		ansx+=x[i];
		ansy+=y[i]; 
	}
	ansx=ansx/(db)(n);
	ansy=ansy/(db)(n);
	sa();
	printf("%.3lf %.3lf\n",ansx,ansy);
	return 0;
} 

posted @ 2019-10-14 21:35  lcyfrog  阅读(195)  评论(0编辑  收藏  举报