• UVA10228 模拟退火


    题目链接:

    https://www.luogu.org/problem/UVA10228

    一眼看。很明显嘛,裸的模拟退火

    什么?你不知道什么是模拟退火?出门请右转 https://www.cnblogs.com/btcadmire123A/articles/11248754.html

    如果想要更好的游戏体验,  https://www.cnblogs.com/flashhu/p/8884132.html

    所以::为什么是模拟退火的说?

    看官请看:

    给定一个N边形所有顶点坐标x,y,求其费马点到所有顶点距离和。费马点是指到多边形所有顶点距离和最小的点。

    某大神说:我会计算平面几何+三分,复杂度优秀。 请您左转至题库切了他。

      在这里我提供的是随机化算法(模拟退火)。

        在我看来,退火明显比爬山算法好(虽然都属玄学),因为他有更大几率获得全局最优解,而非局部。

    当然操作还是分为Calc与SA(Simulate Anneal)的啦。

    此时寻找的解是此时的“费马点”到所有顶点的坐标距离(二维距离,非曼哈顿距离)。

    calc操作表示此时解的费马距离(口胡定义,莫要见怪)并实时更新。

    SA操作照样负责找随机解并judge更新否?

    代码若下:

    #include<cstring>
    #include<cmath>
    #include<cstdio>
    #include<cctype>
    #include<ctime>
    #include<algorithm>
    #include<iostream>
    
    using namespace std;
    
    #define maxn 10050
    
    int x[1005],y[1005],n,T;
    double ansx,ansy,ans;
    
    int read();
    double calc(double a,double b);
    void SA();
    void work();
    
    int main(){
        T=read();
        while(T--){
            n=read();
            for(int i=1;i<=n;i++)    x[i]=read(),y[i]=read();
            ansx=ansy=0;ans=calc(0,0);
            work();
            cout<<(int)(ans+0.5)<<endl;
            if(T) cout<<endl;
        }
    }
    
    int read(){
        int ans=0,f=1;char t;
        while(t<'0'||t>'9') {if(t=='-') f=-1;t=getchar();}
        while(t>='0'&&t<='9') ans=ans*10+t-'0',t=getchar();
        return ans*f;
    }
    
    double calc(double a,double b){
        double ret=0;
        for(int i=1;i<=n;i++) ret+=sqrt((x[i]-a)*(x[i]-a)+(y[i]-b)*(y[i]-b));
        return ret;
    }
    
    void SA(){
        double x=ansx,y=ansy;
        for(double Temp=50001;Temp>=0.00000001;Temp*=0.98){
            double nx=Temp*(rand()*2-RAND_MAX)+x;
            double ny=Temp*(rand()*2-RAND_MAX)+y;
            double nans=calc(nx,ny);
            double bet=nans-ans;
            if(bet<0) ans=nans,x=ansx=nx,y=ansy=ny;
            else if(exp(-bet/Temp)*RAND_MAX>rand()) x=nx,y=ny;
        }
    }
    
    void work(){
        for(int i=1;i<=15;i++) SA();
    }

    我才不会告诉你我没有UVA账号,不能提交。 我也不知道它能不能AC。

  • 相关阅读:
    渐变的圆
    画一组同心圆
    画五角星
    照猫画虎求阶乘
    字符串逆序输出
    格式化输出
    计算矩形面积
    字符串反码A
    快乐数字
    Maratona Brasileira de Popcorn( 二分答案+暴力 )
  • 原文地址:https://www.cnblogs.com/btcadmire123A/p/11252449.html
Copyright © 2020-2023  润新知