模板:模拟退火
文章目錄
- 前言
- 解析
- 流程
- 示例代碼
- trick
所謂模擬退火,就是通過代碼模擬退火
(逃)
前言
終于學了這個神奇的騙分算法
幾次在大賽中都發現這算法是真的有學的必要
FFC可能真的要想想自己的題目對OI界的導向作用了
但學完以后還是感覺挺有意思的,無腦艸題也很香
似乎絕大多數教程都會在這個地方貼一個百度百科在物理學上對退火的定義
但我并不想貼
因為個人感覺這個算法雖然說是模擬但感覺完全不需要知道任何關于退火的知識…
模擬退火,其實可以理解成模擬降溫
解析
流程
其實模擬退火代碼框架很簡單
總體如下:
就這么短
其中,計算答案優劣變化和初始答案通常會外包一個 calc 函數,也是許多時候決定一個退火算法優劣的關鍵
至于是否接受當前解,分情況來討論:
設答案變化量為 xxx,當前求答案最小值 (降溫)
定性來看,這個東西是和諧的,答案變差的越多,我們接受的概率就越小
示例代碼
P1337 [JSOI2004]平衡點 / 吊打XXX
#include<bits/stdc++.h> using namespace std; #define ll long long #define ull unsigned long long #define debug(...) fprintf(stderr,__VA_ARGS__) const int N=1050; const double eps=1e-12; inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; }int n; double x[N],y[N],w[N]; double T,t,X,Y; void SA(){T=1e5,t=0.95;for(int i=1;i<=n;i++) X+=x[i],Y+=y[i];X/=n;Y/=n;while(T>1e-5){double fx(0),fy(0);for(int i=1;i<=n;i++){double dx=x[i]-X,dy=y[i]-Y;if(abs(dx)<1e-15&&abs(dy)<1e-15) continue;double per=1.0/sqrt(dx*dx+dy*dy);fx+=w[i]*dx*per;fy+=w[i]*dy*per;}X+=fx*T;Y+=fy*T;T*=t;}printf("%.3lf %.3lf\n",X,Y); } signed main() { #ifndef ONLINE_JUDGE//freopen("a.in","r",stdin);//freopen("a.out","w",stdout); #endifn=read();for(int i=1;i<=n;i++){x[i]=read();y[i]=read();w[i]=read();}SA();return 0; } /**/trick
Thanks for reading!
總結
- 上一篇: Canalys:第三季度全球智能手机市场
- 下一篇: 模板:长链剖分