Title

SP34 RUNAWAY - Run Away 题解

前言

一道很简单的模拟退火的水题,但是因为把 l 达成了 1 调了一下午……

解题思路

显然,我们每次随机出一个可能的坐标,然后检验,如果更优,那么直接更新,否则按照一定概率判断是否作为一个可能的解更新。

一些注意事项

首先,记得开 double,因为坐标可能不是整数;其次,注意更新答案的时候,一定要重新定义两个临时的变量存储坐标,不然的话,更新可能的解时会把正确的覆盖掉,导致无法得到正确答案;最后,如果你像我一样八字够硬,那么 SA 函数只需要跑 1 次,初始温度只需要设置在 1000 以上即能通过这道题,本蒟蒻也是成功的拿到了最优解,但是还是推荐大家多跑几次。

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();
}
posted @   UncleSam_Died  阅读(3)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示