模拟退火学习笔记

☆樱花仙子☆ 提交于 2019-12-01 08:52:52

模拟退火学习笔记

膜你颓祸

退火

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

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

模拟退火

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

形式化地,对于当前一个新解\(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;
} 
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!