-
时间:2016-04-14 21:43:30 星期四
-
题目编号:[2016-04-14][POJ][203][Building a Space Station]
-
题目大意:给定n个球体,每个球体可能重合,可能包含,可能分离,问把每个球体连接起来(重合和包含看做已经连接),至少需要多长的路
-
分析:最小生成树,边权为 max(0,disij?ri?rj)max(0,disij?ri?rj),即重合和内含,边权为0
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 100 + 10;
double g[maxn][maxn],lowc[maxn];
int vis[maxn];
struct Point{
double x,y,z,r;
Point(double a = 0,double b = 0,double c = 0,double d = 0):x(a),y(b),z(c),r(d){}
}p[maxn];
double dtmp(double a,double b){
return (a - b)*(a - b);
}
double dis(int a,int b){
return sqrt(dtmp(p[a].x,p[b].x) + dtmp(p[a].y,p[b].y) + dtmp(p[a].z,p[b].z));
}
double prim(int n){
memset(vis,0,sizeof(vis));
vis[0] = 1;
for(int i = 1 ; i < n ; ++i){
lowc[i] = g[0][i];
}
double ans = 0;
for(int i = 1 ; i < n ; ++i){
double minc = 999999999;
int p = -1;
for(int j = 0 ; j < n ; ++j){
if(!vis[j] && minc > lowc[j]){
minc = lowc[j];
p = j;
}
}
if( minc == 999999999) return -1;
ans += minc;
vis[p] = 1;
for(int j = 0 ; j < n ; ++j){
if(!vis[j] && lowc[j] > g[p][j]){
lowc[j] = g[p][j];
}
}
}
return ans;
}
int main(){
int n;
while(~scanf("%d",&n) && n){
double a,b,c,d,tmp;
for(int i = 0 ; i < n ; ++i){
scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
p[i] = Point(a,b,c,d);
}
for(int i = 0 ; i < n ; ++i){
for(int j = 0 ; j < n ; ++j){
tmp = dis(i,j) - p[i].r - p[j].r;
g[i][j] = max(double(0.0),tmp);
}
}
printf("%.3f\n",prim(n));
}
return 0;
}
时间: 2024-10-24 15:15:11