模板:模拟退火

double ansx,ansy; //全局最优解的坐标
double ans=1e18,t; //全局最优解、温度
const double delta=0.993; //降温系数

inline double calc_energy() { //计算整个系统的能量
	return 0;
}

void simulate_anneal() { //SA主过程
    double x=ansx,y=ansy;
    t=2000; //初始温度
    while (t>1e-14) {
        double X=x+((rand()<<1)-RAND_MAX)*t;
        double Y=y+((rand()<<1)-RAND_MAX)*t; //得出一个新的坐标
        double now=calc_energy();
        double Delta=now-ans;
        if (Delta<0) { //接受
            x=X,y=Y;
            ansx=x,ansy=y,ans=now;
        }
        else if (exp(-Delta/t)*RAND_MAX>rand()) x=X,y=Y; //以一个概率接受
        t*=delta;
    }
}

inline void Solve() { //多跑几遍SA,减小误差
    ansx=(double)sx/n,ansy=(double)sy/n; //从平均值开始更容易接近最优解
    simulate_anneal();
    simulate_anneal();
    simulate_anneal();
}
//#include <bits/stdc++.h>
#include <math.h>
#include <cstdio>
#include <iostream>
#include <cstring>
#define int long long
using namespace std;
const int mod = 1e9+7;
struct node{
    double x,y,z;
}p[1005];
int n;

double dis(double xx,double yy,double zz,int i){
    double x = xx-p[i].x;
    double y = yy-p[i].y;
    double z = zz-p[i].z;
    return sqrt(x*x+y*y+z*z);
}

double sa(){
    double EPS = 1e-9;
    double T = 100000;
    double delta = 0.98;
    double res = 1e18;
    double x = 0,y = 0,z = 0;
    while(T > EPS){
        double diss = 0;
        int d = 0;
        for(int i = 0 ; i < n ; i ++){
            double tmp = dis(x,y,z,i);
            if(tmp > diss){
                diss = tmp;
                d = i;
            }
        }
        res = min(res,diss);
        x += (p[d].x - x)/diss*delta*T;
        y += (p[d].y - y)/diss*delta*T;
        z += (p[d].z - z)/diss*delta*T;

        T *= delta;
    }
    return res;
}

signed main(){
    while(~scanf("%lld",&n) && n){
        for(int i = 0 ; i < n ; i ++)
            scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].z);
        printf("%.15f\n",sa());
    }
    return 0;
}



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值