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