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

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章