标签:ch int double down while 模拟退火
模拟退火
模拟退火是一种 著名的 玄学的随机化算法,其建立在物理中退火过程的基础上
其时间复杂度为 \(O(\text{时限})\) ,正确概率为 \(\text{(参数优秀程度+阳寿)}\%\)
通常人们使用造数据+手动二分调参的方式来提高正确率
这种算法是 \(oier\) 在比赛中的不二选择
#include<bits/stdc++.h>
using namespace std;
#define down 0.97
const int N=1e5+5;
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
int n;
double x[N],y[N];
double ansx,ansy,ans;
//cal函数因题而异,是用于求解某一点的答案
inline double cal(double u,double v){
double res=0;
for(int i=1;i<=n;++i){
res+=sqrt((u-x[i])*(u-x[i])+(v-y[i])*(v-y[i]));
}
return res;
}
inline void SimulateAnneal(){
double t=3000,mt=1e-10;//t指初始温度,mt指结束温度
double nowx=ansx,nowy=ansy;
for(;t>=mt;t*=down){//t每次*down表示降温
double nx=nowx+(rand()*2-RAND_MAX)*t;//常规随机数据
double ny=nowy+(rand()*2-RAND_MAX)*t;
double nows=cal(nx,ny);
double delta=nows-ans;//记录差值
if(delta<0) ansx=nx,ansy=ny,nowx=nx,nowy=ny,ans=nows;//若当前答案更优,则更新
else if(exp(-delta/t)*RAND_MAX>rand()) nowx=nx,nowy=ny;//否则概率更新
}
}
signed main(){
srand(time(0));
int T;
cin>>T;
for(int i=1;i<=T;++i){
cin>>n;
ans=1e9,ansx=ansy=0;
for(int i=1;i<=n;++i){
cin>>x[i]>>y[i];
ansx+=x[i],ansy+=y[i];
}
ansx/=n,ansy/=n;//初始答案
int B=50;
while(B--) SimulateAnneal();//跑多次模拟退火
cout<<round(ans)<<endl;
if(i!=T) cout<<endl;
}
}
标签:ch,int,double,down,while,模拟退火 来源: https://www.cnblogs.com/into-qwq/p/16488256.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。