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

本文深入探讨了模拟退火算法在解决平衡点问题中的应用,通过随机数优化,寻找n个重物达到平衡状态时的位置。文章提供了详细的AC代码实现,强调了降温系数对时间复杂度的影响,并介绍了如何通过多次退火提高解的准确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

题意

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

20190917092717.png

分析

模拟退火基础题,基于随机数的优化算法,时间复杂度玄学,参数玄学,能不能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;
}

转载于:https://www.cnblogs.com/sstealer/p/11531698.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值