• 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;
    }
    
  • 相关阅读:
    #2019090700004
    51nod 1191-贪心+并查集
    hdu 5015-矩阵快速幂
    树形DP—依赖背包模板
    HDU 1074—压缩DP
    动态绑定的开销
    动态绑定
    静态绑定(前期绑定)
    继承的一些优点
    多态置换原则初始化基类对象
  • 原文地址:https://www.cnblogs.com/wzgg/p/11518734.html
Copyright © 2020-2023  润新知