• # [洛谷1337] 吊打XXX/平衡点 (模拟退火)


    [洛谷1337] 吊打XXX/平衡点 (模拟退火)

    题意

    n个重物(x,y,w),求平衡时x的位置(x,y)

    分析

    模拟退火基础题,基于随机数的优化算法,时间复杂度玄学,参数玄学,能不能AC看脸,当然如果参数设定的好,并且在规定时间内多跑几次退火算法,并且每次退火时以上一次退火得到的最优解作为新一次退火的起点,AC的概率还是很大的。

    ACcode

    #include <bits/stdc++.h>
    #define fre freopen("data.in","r",stdin);
    #define frew freopen("my.out","w",stdout);
    using namespace std;
    int n;
    struct node{
        int x,y,w;
    }s[2005];
    double ansx,ansy,answ;
    double sx,sy,sw;
    double energy(double x,double y){
        double ans=0,dx,dy;
        for(int i=0;i<n;i++){
            dx=x-s[i].x;
            dy=y-s[i].y;
            ans+=(sqrt(dx*dx+dy*dy)*s[i].w);
        }
        return ans;
    }
    
    void sa(){
        /*
         *影响时间复杂度的主要是降温系数,初始温度和截止温度影响不大,
         *降温系数相差一个数量级,时间增加一个数量级
        */
        double t=3000;
        double down=0.996;
        sx=ansx,sy=ansy;//以当前获取的最优解作为退火的起点
    
        while(t>1e-15){//当前温度大于设定的停止退火温度,则继续执行退火操作
            //在当前最优解的周围随机出一个新的解
            double ex=sx+((rand()<<1)-RAND_MAX)*t;
            double ey=sy+((rand()<<1)-RAND_MAX)*t;
            double ew=energy(ex,ey);
            double dif=ew-answ;
    
            if(dif<0){//新解比最优解要优,更新最优解
                ansx=ex,ansy=ey,answ=ew;
                sx=ex,sy=ey;
            }
            else if(exp(-dif/t)*RAND_MAX>rand()){
                sx=ex;
                sy=ey;
            }
            t*=down;
        }
    }
    double MIN_TIME=0.8;
    
    void solve(){
        while((double)clock()/CLOCKS_PER_SEC<MIN_TIME){//在可接受的时间内多执行几次退火
            //cout<<clock()<<endl;
            sa();
            //cout<<ansx<<ansy<<endl;
        }
    }
    int main(){
        //fre;frew;
        cin>>n;
        for(int i=0;i<n;i++){
            cin>>s[i].x>>s[i].y>>s[i].w;
            ansx+=s[i].x;
            ansy+=s[i].y;
        }
        //初始化解空间为质心
        ansx/=n,ansy/=n;
        answ=energy(ansx,ansy);
    
        solve();
        printf("%.3lf %.3lf",ansx,ansy);
        return 0;
    }
    
  • 相关阅读:
    剑指offer39-平衡二叉树
    剑指offer37-数字在排序数组中出现的次数
    剑指offer36-两个链表的第一个公共结点
    剑指offer31-整数中1出现的次数
    剑指offer30-连续子数组的最大和
    剑指offer28-数组中出现次数超过一半的数字
    剑指offer26-二叉搜索树与双向链表
    剑指offer21-栈的压入、弹出序列
    剑指offer16-合并两个排序的链表
    C#-杂碎
  • 原文地址:https://www.cnblogs.com/sstealer/p/11531698.html
Copyright © 2020-2023  润新知