时间:2016-04-14 21:43:30 星期四
题目编号:[2016-04-14][POJ][203][Building a Space Station]
题目大意:给定n个球体,每个球体可能重合,可能包含,可能分离,问把每个球体连接起来(重合和包含看做已经连接),至少需要多长的路
分析:最小生成树,边权为 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;}