SP34 RUNAWAY - Run Away 题解
前言
一道很简单的模拟退火的水题,但是因为把 l 达成了
解题思路
显然,我们每次随机出一个可能的坐标,然后检验,如果更优,那么直接更新,否则按照一定概率判断是否作为一个可能的解更新。
一些注意事项
首先,记得开 double,因为坐标可能不是整数;其次,注意更新答案的时候,一定要重新定义两个临时的变量存储坐标,不然的话,更新可能的解时会把正确的覆盖掉,导致无法得到正确答案;最后,如果你像我一样八字够硬,那么 SA 函数只需要跑
AC 代码
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<algorithm>
//最低温度
#define MINT 1e-2
//模拟退火次数
#define MAXT 1
//设置降温速率
#define DT 0.97
#define N 1005
#define inf 1e9
int X,Y,M,x[N],y[N];
double ansx,ansy,anx,any;
double ans;
inline double Dis(double x1,double y1,double x2,double y2){
double Oler_X=(x1-x2)*(x1-x2);
double Oler_Y=(y1-y2)*(y1-y2);
return sqrt(Oler_X+Oler_Y);
}
inline double Clac(double nx,double ny){
double res=inf;
for(register int i=1;i<=M;++i){
double x1=nx,y1=ny;
double x2=x[i]*1.0;
double y2=y[i]*1.0;
double dis=Dis(x1,y1,x2,y2);
res=std::min(res,dis);
}return res;
}
inline double Rand(double l,double r){
if(l>r) std::swap(l,r);
return rand()*(r-l)/RAND_MAX+l;
}inline void SA(){
double T=1145.0;//设置初始温度
anx=ansx,any=ansy;
while(T>MINT){
double _x=Rand(std::max(anx-T,0.0),std::min(anx+T,X*1.0));
double _y=Rand(std::max(any-T,0.0),std::min(any+T,Y*1.0));
double dis=Clac(_x,_y);
double Delta=dis-ans;
if(Delta>0){//这是一个更优解
ansx=_x,ansy=_y;
ans=dis;
anx=_x,any=_y;
}else{
if(exp(Delta/T)>rand()){
anx=_x;any=_y;
}
}T=T*DT;
}
}inline void work(){
scanf("%d%d%d",&X,&Y,&M);
for(register int i=1;i<=M;++i)
scanf("%d%d",&x[i],&y[i]);
ansx=Rand(0.0,X);
ansy=Rand(0.0,Y);
ans=Clac(ansx,ansy);
for(register int i=1;i<=MAXT;++i) SA();
printf("The safest point is (%.1lf, %.1lf).\n",ansx,ansy);
}signed main(){
//设置随机种子
srand(114514);
//设置随机的随机种子
srand(rand()%191981);
int T;scanf("%d",&T);
while(T--) work();
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下