2018 ACM-ICPC 南京站 D Country Meow 最小球覆蓋(模擬退火&三分)

//模擬退火
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const double eps=1e-8;
struct point3D
{
    double x,y,z;
} data[105];
int n;
double dis(point3D a,point3D 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 step=10000,ans=1e30,mt;
    point3D z;
    z.x=z.y=z.z=0;
    int s=0;
    while(step>eps)
    {
        for(int i=0; i<n; i++)
            if(dis(z,data[s])<dis(z,data[i])) s=i;
        mt=dis(z,data[s]);
        ans=min(ans,mt);
        z.x+=(data[s].x-z.x)/mt*step;
        z.y+=(data[s].y-z.y)/mt*step;
        z.z+=(data[s].z-z.z)/mt*step;
        step*=0.98;
    }
    return ans;
}
int main()
{
    double ans;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=0; i<n; i++)
            scanf("%lf%lf%lf",&data[i].x,&data[i].y,&data[i].z);
        ans=solve();
        printf("%.7f\n",ans);
    }
    return 0;
}
//三分
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e2+5;
const double eps=1e-7;
typedef struct {double p[3];}point;
point a[maxn];
int n;
double cal(point now)
{
    double ans=0.0;
    for(int i=0;i<n;i++)
        ans=max(ans,sqrt((a[i].p[0]-now.p[0])*(a[i].p[0]-now.p[0])+(a[i].p[1]-now.p[1])*(a[i].p[1]-now.p[1])+(a[i].p[2]-now.p[2])*(a[i].p[2]-now.p[2])));
    return ans;
}
point del(point now,int cnt)
{
    if(cnt>=3)
        return now;
    double r=100000,l=-100000;
    double dr,dl;
    point tp1,tp2,ans1,ans2,ans;
    tp1=tp2=ans=now;
    while(r-l>eps)
    {
        dr=(2*r+l)/3;
        dl=(2*l+r)/3;
        tp1.p[cnt]=dl;
        tp2.p[cnt]=dr;
        ans1=del(tp1,cnt+1);
        ans2=del(tp2,cnt+1);
        if(cal(ans1)>cal(ans2))
        {
            l=dl;
            ans=ans1;
        }
        else
        {
            r=dr;
            ans=ans2;
        }
    }
    return ans;
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=0;i<n;i++)
            scanf("%lf%lf%lf",&a[i].p[0],&a[i].p[1],&a[i].p[2]);
        point ans;
        printf("%lf\n",cal(del(ans,0)));
    }
    return 0;
}
/*
3
0 0 0
3 0 0
0 4 0
4
0 0 0
1 0 0
0 1 0
0 0 1
5
0 1 2
2 3 4
5 6 7
7 8 9
9 2 3
*/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章