思路:
- 最小生成树,PRIM 。
- 存储所有点,邻接矩阵存图。
- 除了松弛没什么特殊的了。
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>
#include <cmath>
#define MAXV 1e5
using namespace std;
const int maxn = 105;
int N;
double ans;
bool vis[maxn];
double dis[maxn];
double mp[maxn][maxn];
struct CELL{
double x,y,z,r;
}cell[maxn];
void ADDCELL(int i,double x,double y,double z,double r){
cell[i].x = x;
cell[i].y = y;
cell[i].z = z;
cell[i].r = r;
return ;
}
struct NODE{
int id;
double dis;
NODE(int id,double dis) : id(id) , dis(dis) {} ;
friend bool operator > (NODE a , NODE b){
return a.dis > b.dis ;
}
};
priority_queue <NODE , vector<NODE> , greater<NODE> > Q;
void INIT(){
ans = 0;
memset(vis , 0 , sizeof(vis));
for(int i=1;i<=N;i++)
dis[i] = MAXV;
return ;
}
void PRIM(){
dis[1] = 0;
Q.push(NODE(1 , 0));
while(Q.size()){
NODE cur = Q.top() ; Q.pop() ;
int id = cur.id ;
if(vis[id])
continue;
vis[id] = true;
ans += dis[id];
for(int i=1;i<=N;i++){
if(id == i)
continue;
if((cell[id].r + cell[i].r) > sqrt(mp[id][i])){
dis[i] = 0;
Q.push(NODE(i , 0));
continue;
}
if(dis[i] > sqrt(mp[id][i]) - cell[id].r - cell[i].r){
dis[i] = sqrt(mp[id][i]) - cell[id].r - cell[i].r;
Q.push(NODE(i , dis[i]));
}
}
}
return ;
}
int main(){
while(cin>>N && N){
INIT();
for(int i=1;i<=N;i++){
double x,y,z,r;
cin>>x>>y>>z>>r;
ADDCELL(i,x,y,z,r);
}
for(int i=1;i<=N;i++){
double xi = cell[i].x;
double yi = cell[i].y;
double zi = cell[i].z;
for(int j=i;j<=N;j++){
double xj = cell[j].x;
double yj = cell[j].y;
double zj = cell[j].z;
mp[i][j] = mp[j][i] = (xi-xj)*(xi-xj) + (yi-yj)*(yi-yj) + (zi-zj)*(zi-zj) ;
}
mp[i][i] = 0;
}
PRIM();
printf("%.3f\n" , ans);
}
return 0;
}