D Country Meow(最小球覆盖模板题,模拟退火算法)

49 篇文章 0 订阅
45 篇文章 0 订阅

In the 24th century, there is a country somewhere in the universe, namely Country Meow. Due to advanced technology, people can easily travel in the 3-dimensional space.
There are N cities in Country Meow. The i-th city is located at (xi, yi, zi) in Cartesian coordinate.
Due to the increasing threat from Country Woof, the president decided to build a new combatant command, so that troops in different cities can easily communicate. Hence, the Euclidean distance between the combatant command and any city should be minimized.
Your task is to calculate the minimum Euclidean distance between the combatant command and the farthest city.

Input

The first line contains an integer N (1 ≤ N ≤ 100).
The following N lines describe the i-th city located.Each line contains three integers xi, yi, zi(−100000 ≤ xi, yi, zi ≤ 100000).

Output

Print a real number — the minimum Euclidean distance between the combatant command and the farthest city. Your answer is considered correct if its absolute or relative error does not exceed 10−3. Formally, let your answer be a, and the jury’s answer be b. Your answer is considered correct if |a−b| max(1,|b|) ≤ 10−3.

standard input

3
0 0 0
3 0 0
0 4 0
4
0 0 0
1 0 0
0 1 0
0 0 1

standard output

2.500000590252103
0.816496631812619



题意:

给定3维空间中N个点,求一个点使得其到最远点的距离最小(即令其到所有点的距离都尽可能的小),输出该点到最远点的距离。(精确到10-3

那么也就是要求一个最小的球,使其覆盖(包含)所有的N个点,输出该球的半径。



分析:

利用模拟退火算法逐步逼近目标的球心,有关模拟退火算法,感觉这位的写的很好:https://blog.csdn.net/AI_BigData_wh/article/details/77943787?locationNum=2&fps=1

关于模拟退火算法的核心思想,有个比喻就是:兔子喝醉了。它随机地跳了很长时间。这期间,它可能走向高处,也可能踏入平地。但是,它渐渐清醒了并朝最高方向跳去。这就是模拟退火。

模拟退火有一个初始温度,温度越高,接受较差的解的可能性就越大。每次走完后,都会降低温度,使得接受较差解的可能性变小。在走的过程中,更新最优解的值。

在求最小球覆盖时,只需要从某个初始点开始,一直向离它最远的那个点靠近,但每次要以一定的概率去靠近,那么该概率就是 p = T/start_T,温度T以一定的速率下降,温度T越低时这一次则越可能达到更优解。

而精确度则由start_T、精度eps以及下降速率rate决定,综合考虑就是让循环次数越多越精确。



以下代码:

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=150;
const double eps=1e-3;       //精度
const double start_T=1000;   //初始温度
const double rate=0.98;      //温度下降速率
struct point
{
    double x;
    double y;
    double z;
} p[maxn];
int N;
double dist(point a,point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));
}
double solve()
{
    double T=start_T;
    point ans_p={0,0,0};  //初始点
    double ans=1e99;      //预设一个较大值
    while(T>eps)
    {
        point maxd_p=p[1];
        for(int i=2;i<=N;i++)
        {
            if(dist(ans_p,p[i])>dist(ans_p,maxd_p))
                maxd_p=p[i];
        }
        //找到距离ans_p最远的点,maxd_p
        ans=min(ans,dist(ans_p,maxd_p));
        ans_p.x+=(maxd_p.x-ans_p.x)*(T/start_T);    //以一定概率靠近maxd_p
        ans_p.y+=(maxd_p.y-ans_p.y)*(T/start_T);
        ans_p.z+=(maxd_p.z-ans_p.z)*(T/start_T);
        T*=rate;
    }
    return ans;
}
int main()
{
    scanf("%d",&N);
    for(int i=1;i<=N;i++)
        scanf("%lf %lf %lf",&p[i].x,&p[i].y,&p[i].z);
    printf("%.8lf",solve());
    return 0;
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值