题意:给你N个细胞之类的东西,简单理解为球,这是立体的所以球心坐标是x,y,z这样的,然后给你一个球的半径,然后把这些球连接起来,如果两个球之间不想交,那么修建一条道路连起来,如果相交,那么不需要修路,求修路的最短是多少,其实就是最小生成树
思想:不想交距离等于两个点之间距离减去两个球半径,相交距离为0;
这个题除了一晚上bug原来是自己的distance和库函数重名了,改成dist调用就好了
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<iostream>
#include<algorithm>
#define maxn 120
#define INF 0x3f3f3f3f
using namespace std;
double map[maxn][maxn];
bool vis[maxn];
double d[maxn];
int n;
struct Node
{
double x,y,z,r;
}node[maxn];
double dist(int i, int j)
{
double X = node[i].x - node[j].x;
double Y = node[i].y - node[j].y;
double Z = node[i].z - node[j].z;
double dis = sqrt(X*X + Y*Y + Z*Z);
double len = node[i].r + node[j].r;
if(dis > len)
return (dis - len);
else return 0;
}
void prime()
{
for(int i = 1; i <= n; i ++)
{
d[i] = map[1][i];
vis[i] = 0;
}
for(int i = 1; i <= n; i ++)
{
double minx = INF;
int now;
for(int j = 1; j <= n; j ++)
{
if(!vis[j] && d[j] < minx)
{
minx = d[j];
now = j;
}
}
vis[now] = 1;
for(int k = 1; k <= n ; k ++)
{
if(!vis[k] && d[k] > map[now][k])
d[k] = map[now][k];
}
}
double sum = 0;
for(int i = 1; i <= n; i ++)
sum += d[i];
printf("%.3f\n",sum);
}
int main()
{
while(~scanf("%d",&n) && n)
{
for(int i = 1; i <= n; i ++)
scanf("%lf%lf%lf%lf",&node[i].x,&node[i].y,&node[i].z,&node[i].r);
memset(map,0,sizeof(map));
for(int i = 1; i <= n; i ++)
for(int j = i + 1; j <=n; j ++)
{
map[i][j] = map[j][i] = dist(i,j);
}
prime();
}
return 0;
}