题意:
在一个三位平面上有几个球体,然后输入数据是给你N个球的球心坐标,以及半径。科学家们想要实现各个球之间的接触,也就是有表面的接触。当然,两个球之间可能会有相交的地方( dis(a,b) <= 0 ),那么这两个球是不用你新建道路来实现想通的。
思路:
求每个球之间球面的距离然后最小生成树就行了。水……
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#include<iomanip>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn=105;
const double eps=1e-8;
const double PI = acos(-1.0);
ll gcd(ll a,ll b)
{
return b==0?a:gcd(b,a%b);
}
struct node
{
double x,y,z,r;
};
double dis(node a,node b)
{
double t=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))-a.r-b.r;
return t>0?t:0;
}
node a[maxn];
int vis[maxn];
double lowc[maxn];
double prim(double cost[][maxn],int n)
{
double ans=0;
memset(vis,0,sizeof(vis));
for(int i=1;i<n;i++)
{
lowc[i]=cost[0][i];
}
vis[0]=1;
for(int i=0;i<n-1;i++)
{
double minc=inf;
int p;
for(int j=0;j<n;j++)
{
if(!vis[j]&&minc>lowc[j])
{
p=j;
minc=lowc[j];
}
}
if(minc==inf) return -1;
ans+=minc;
vis[p]=1;
for(int j=0;j<n;j++)
{
if(!vis[j]&&lowc[j]>cost[p][j])
{
lowc[j]=cost[p][j];
}
}
}
return ans;
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int n;
while(cin>>n&&n)
{
for(int i=0;i<n;i++)
{
cin>>a[i].x>>a[i].y>>a[i].z>>a[i].r;
}
double g[maxn][maxn];
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
if(i==j) g[i][j]=0;
else
{
g[i][j]=g[j][i]=dis(a[i],a[j]);
}
}
}
cout<<fixed<<setprecision(3)<<prim(g,n)<<endl;
}
return 0;
}