cf2c(模拟退火 步长控制

Posted wzgg

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cf2c(模拟退火 步长控制相关的知识,希望对你有一定的参考价值。

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]*delta[i];
    
    return ret;        //返回误差的平方和

int main() 
    bool mark;
    double x=0.0,y=0.0;
    for(int i=0;i<3;++i) 
        scanf("%lf%lf%lf",&P[i].x,&P[i].y,&P[i].r);
        x+=P[i].x/3;
        y+=P[i].y/3;    //设置近似最优解为三个圆圆心构成的三角形重心
    
    for(double t=1.0,delta;t>EPS;)     //初始步长为1
        mark=0;                            //搜索标记
        delta=Check(x,y);
        if(Check(x+t,y)<delta)     //搜索更优解
            x+=t;
            mark=1;
        
        else if(Check(x-t,y)<delta) 
            x-=t;
            mark=1;
        
        else if(Check(x,y+t)<delta) 
            y+=t;
            mark=1;
        
        else if(Check(x,y-t)<delta) 
            y-=t;
            mark=1;
        
        if(!mark)    //搜索不到调整步长
            t/=2;
    
    if(fabs(Check(x,y))<EPS)        //检查
        printf("%.5lf %.5lf",x,y);
    return 0;

 

以上是关于cf2c(模拟退火 步长控制的主要内容,如果未能解决你的问题,请参考以下文章

OpenAI Gym 关于CartPole的模拟退火解法

OpenAI Gym 关于CartPole的模拟退火解法

POJ 1379 Run Away(模拟退火)

浅谈模拟退火

模拟退火

模拟退火