模拟退火

模拟退火学习笔记

☆樱花仙子☆ 提交于 2019-12-01 08:52:52
目录 模拟退火学习笔记 退火 模拟退火 优缺点 伪代码 吊打LCY(模板) 模拟退火学习笔记 膜你颓祸 退火 在每个温度都有几率跳到一个劣与当前的位置,温度越低,劣解的采纳率更低 因为在每个温度都有足够的时间来找到合适的位置,所以最后答案接近正确 模拟退火 就是在解决一类问题中模拟上述方法 形式化地,对于当前一个新解 \(f(x)\) ,有 \(f(x')>f(x)\) ,取此解 \(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

Country Meow(模拟退火入门)

余生长醉 提交于 2019-12-01 08:49:21
题目链接: http://codeforces.com/gym/101981/attachments 题意:给你n个三维空间点(n<=100)要求找到一个离所有点最远的距离最小的点,并输出这个距离 思路:模拟退火,首先取一个值,代表答案点在的位置,然后暴力一遍所有的点,会得到里当前点最远的点是哪个 然后更新当前ans ,并且往这个最远的点移动,贪心,最后就是答案了 看代码: #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include<map> #include<cstdlib> using namespace std; typedef long long LL; const LL mod=1e9+7; const LL INF=1e9+7; const int maxn=1e2+50; const double StartT=50000;//初始温度 1000也可以过这道题 const double rate=0.99;//退火系数 一般0.97-0.99 const double eps=1e-6;//精度 可以在题目要求的小数点后面位数多加3左右 const double FINF=1e18; /**

模拟退火

杀马特。学长 韩版系。学妹 提交于 2019-12-01 07:48:23
本文转自:https://www.cnblogs.com/shenben/p/11342308.html 来源: https://www.cnblogs.com/chen99/p/11670307.html

2018南京现场赛D 模拟退火

こ雲淡風輕ζ 提交于 2019-12-01 07:48:19
题目链接:https://codeforces.com/gym/101981/attachments 给你n个城市的三维坐标,叫你求得一个坐标使这个坐标到其他城市的最大距离最小,并输出这个距离(距离不唯一,只要在一定误差内即可)。因为城市的数量不多而且要求的距离不是一个确定值,只需在一定误差内,所以模拟退火跑就完事。 #include<iostream> #include<algorithm> #include<cmath> using namespace std; const double eps=1e-8; #define inf 0x3f3f3f3f int n; struct node{ double x,y,z; node(){}; node(double x,double y,double z):x(x),y(y),z(z){}; double dis(node w) { return sqrt((w.x-x)*(w.x-x)+(w.y-y)*(w.y-y)+(w.z-z)*(w.z-z)); } }p[105],a; int main() { scanf("%d",&n); double x,y,z; for(int i=1;i<=n;i++) { scanf("%lf%lf%lf",&x,&y,&z); p[i]=node(x,y,z); } a=node(0,0

模拟退火

偶尔善良 提交于 2019-11-30 18:35:48
一、什么是模拟退火算法 1、爬山算法 在了解模拟退火算法之前,先来看一下爬山算法:爬山算法是一种贪心算法,该算法每次从当前的解空间中选取一个解作为最优解,直到达到一个局部最优解。假设函数f(x)的图像如下图: 现在使用爬山算法来求f(x)的最大值,若C为当前最优解,则爬山算法搜索到A就会停止搜索,这会获得一个局部最优解,而不是全局最优解。 模拟退火:继续考虑寻找f(x)最大值的问题,爬山算法搜索到A点时就会停止搜索,原因是A点左右的值均小于A点的值。模拟退火算法采用的解决办法是以一定的概率选择A两边的点,尽管A两边的点并不是局部最优解,这样就有一定的概率搜索到D点,从而搜索到B点,最终获得了全局最优解。 2、模拟退火算法 现在想求函数的(全局)最优解。如果采用Greedy策略,那么从A点开始试探,如果函数值继续减少,那么试探过程就会继续。而当到达点B时,显然我们的探求过程就结束了(因为无论朝哪个方向努力,结果只会越来越大)。最终我们只能找打一个局部最后解B。 模拟退火其实也是一种Greedy算法,但是它的搜索过程引入了随机因素。模拟退火算法以一定的概率来接受一个比当前解要差的解,因此有可能会跳出这个局部的最优解,达到全局的最优解。以上图为例,模拟退火算法在搜索到局部最优解B后,会以一定的概率接受向右继续移动。也许经过几次这样的不是局部最优的移动后会到达B 和C之间的峰点

模拟退火 [JSOI2004]平衡点 / 吊打XXX

一曲冷凌霜 提交于 2019-11-30 06:31:51
本人水平有限,题解不到为处,请多多谅解 本蒟蒻谢谢大家观看 题目 : 传送门 大致的模拟退火讲解我这里不再赘述,如有疑问请看这里 传送门连接 code: #include <bits/stdc++.h> #define down 0.996//徐徐降温 using namespace std; int n; struct node{ int x; int y; int w; }object[2005];//存下物体的坐标 double ansx,ansy,answ;//最终答案 double energy(double x,double y)//根据物理学知识,能量总和越小越稳定 { double r=0,dx,dy; for (int a=1;a<=n;a++) { dx=x-object[a].x; dy=y-object[a].y; r+=sqrt(dx*dx+dy*dy)*object[a].w; } return r; } void sa()//模拟退火 { double t=3000;//温度要足够高 while (t>1e-15)//略大于0 { //生成[-T*RAND_MAX,T*RAND_MAX)的随机变动范围(rand():[0,RAND_MAX)) //rand()一个随机数,RAND_MAX随机范围内最大值 double ex=ansx+(rand()*2

cf2c(模拟退火 步长控制

梦想与她 提交于 2019-11-29 13:40:01
https://www.luogu.org/problem/CF2C 题意:在平面上有三个没有公共部分的圆,求平面上一点使得到三个圆的切线的夹角相等。(若没答案满足条件,则不打印 思路:可用模拟退火算法来枚举答案点,可过,然而应该不是正解。先设一个最优解和初始步长,然后以当前步长不断搜索最优解更新答案,若答案不能更新,则步长减半再搜索,直到精度达到要求结束算法。 #include<cstdio> #include<cmath> const double EPS=1E-5; //控制精度 struct Point { double x,y; double r; }P[3]; double Get(double x,double y,const Point b) { //求两点之间的距离 return sqrt((x-b.x)*(x-b.x)+(y-b.y)*(y-b.y)); } double Check(double x,double y) { //估价函数 double t[3],delta[3],ret=0.0; //t为当前视角,delta表示误差值 for(int i=0;i<3;++i) t[i]=Get(x,y,P[i])/P[i].r; for(int i=0;i<3;++i) { delta[i]=t[i]-t[(i+1)%3]; ret+=delta[i]

浅谈玄学算法——模拟退火

十年热恋 提交于 2019-11-27 03:40:42
浅谈玄学算法——模拟退火                                           转载自 洛谷 初级篇 本篇讲解SA的基本概念。 如果您已经了解SA的基本概念,您可以跳过这一段。 简介 模拟退火算法(Simulate Anneal,SA)是一种通用概率演算法,用来在一个大的搜寻空间内找寻命题的最优解。模拟退火是由S.Kirkpatrick, C.D.Gelatt和M.P.Vecchi在1983年所发明的。V.Černý在1985年也独立发明此演算法。模拟退火算法是解决TSP问题的有效方法之一。 模拟退火的出发点是基于物理中固体物质的退火过程与一般组合优化问题之间的相似性。模拟退火算法是一种通用的优化算法,其物理退火过程由加温过程、等温过程、冷却过程这三部分组成。 ——百度百科 简单说,模拟退火是一种随机化算法。当一个问题的方案数量极大(甚至是无穷的)而且不是一个单峰函数时,我们常使用模拟退火求解。 它与爬山算法最大的不同是,在寻找到一个局部最优解时,赋予了它一个跳出去的概率,也就有更大的机会能找到全局最优解。 原理 模拟退火的原理也和金属退火的原理近似:将热力学的理论套用到统计学上,将搜寻空间内每一点想像成空气内的分子;分子的能量,就是它本身的动能;而搜寻空间内的每一点,也像空气分子一样带有“能量”,以表示该点对命题的合适程度

某题 模拟退火

六月ゝ 毕业季﹏ 提交于 2019-11-26 12:53:05
为了防止某天忘了默默的屯下来... #include<ctime> #include<cmath> #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> using namespace std; #define ll long long const double cg=0.973; const int maxn=100005; int n,h[maxn]; int turn[maxn],x; ll ans; inline int abs(int x){return (x^(x>>31))-(x>>31);} ll check(int pos)//模拟位置通过位置知高度再去算代价 { for(register int i=1;i<=pos;++i) turn[i]=h[i]+pos-i; for(register int i=pos+1;i<=n;++i) turn[i]=h[i]+i-pos; int mid=(1+n)>>1;//奇数个显然,偶数个的话左右两个数选谁代价同因为列式子左右两边的两个数和抵消了该数的贡献 nth_element(turn+1,turn+mid,turn+n+1); x=turn[mid]; if(x<pos) x=pos; if(n-pos+1>x) x=n