Country Meow(模拟退火入门)

余生长醉 提交于 2019-12-01 08:49:21

题目链接:http://codeforces.com/gym/101981/attachments

 

题意:给你n个三维空间点(n<=100)要求找到一个离所有点最远的距离最小的点,并输出这个距离

思路:模拟退火,首先取一个值,代表答案点在的位置,然后暴力一遍所有的点,会得到里当前点最远的点是哪个

然后更新当前ans ,并且往这个最远的点移动,贪心,最后就是答案了

看代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<map>
#include<cstdlib>
using namespace std;
typedef long long LL;
const LL mod=1e9+7;
const LL INF=1e9+7;
const int maxn=1e2+50;
const double StartT=50000;//初始温度 1000也可以过这道题
const double rate=0.99;//退火系数 一般0.97-0.99
const double eps=1e-6;//精度 可以在题目要求的小数点后面位数多加3左右
const double FINF=1e18;
/**
没有算退火的复杂度
rate=0.98
T=1000 1026次
T=20000 1175次
T=50000 1220次

rate=0.99
T=50000 2452
**/
int N;
struct Node
{
    double x,y,z;
    Node(){}
    Node(double x1,double y1,double z1)
    {
        x=x1;y=y1;z=z1;
    }
}a[maxn];
double dist(Node n1,Node n2)
{
    return sqrt((n1.x-n2.x)*(n1.x-n2.x)+(n1.y-n2.y)*(n1.y-n2.y)+(n1.z-n2.z)*(n1.z-n2.z));
}
void solve()
{
//    int sum=0;
    double ans=FINF;
//    cout<<ans<<endl;
    double T=StartT;
    Node now=Node(0,0,0);//随机选取一个点
    Node max_p=a[1];//离当前最远的点
    while(T>eps)
    {
//        sum++;
        for(int i=1;i<=N;i++)//寻找里当前最远的点
        {
            if(dist(a[i],now)>=dist(max_p,now))
            {
                max_p=a[i];
            }
        }
        ans=min(ans,dist(now,max_p));
        now.x=(now.x+(max_p.x-now.x)*(T/StartT));
        now.y=(now.y+(max_p.y-now.y)*(T/StartT));
        now.z=(now.z+(max_p.z-now.z)*(T/StartT));
        T=T*rate;
    }
//    cout<<"sum:"<<sum<<endl;
    printf("%.15lf\n",ans);
}
int main()
{
    scanf("%d",&N);
    for(int i=1;i<=N;i++)
    {
        scanf("%lf%lf%lf",&a[i].x,&a[i].y,&a[i].z);
    }
    solve();
    return 0;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!