题目链接:http://poj.org/problem?id=2031
题意:修建太空站每个舱之间的走廊。每个舱都是球体。给出n个舱的三维空间坐标以及球体半径。如果球体之间接触或者相接,就不用修走廊。让你求最短走廊的长度。
题解:有点点坑这个题。。改了好久。。这里的存储其实是 $len(a,b) - r_a - r_b$ 求一下这个存储再以Prim求解即可。注意精度。
代码:
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cmath> 5 using namespace std; 6 const int maxn = 105; 7 const int inf = 0x3f3f3f3f; 8 const double eps = 1e-10; 9 double mp[maxn][maxn]; 10 double dis[maxn]; 11 bool vis[maxn]; 12 int n; 13 14 struct node{ 15 double x; 16 double y; 17 double z; 18 double r; 19 }; 20 21 node cir[maxn]; 22 23 double dist(node a,node b){ 24 double diss = (a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y) + (a.z -b.z) * (a.z - b.z); 25 return sqrt(diss) - a.r - b.r; 26 } 27 28 double prim(){ 29 double ans = 0 ; 30 int k; 31 double minn ; 32 for(int i = 1 ; i <= n ; i++){ 33 dis[i] = inf ; 34 vis[i] = false ; 35 } 36 dis[1] = 0 ; 37 for(int i = 1 ; i <= n ; i++){ 38 minn = inf ; 39 k = 0 ; 40 for(int j = 1 ; j <= n ; j++){ 41 if(minn > dis[j] && !vis[j]){ 42 minn = dis[j] ; 43 k = j ; 44 } 45 } 46 if(minn >= inf) 47 return -1 ; 48 ans += minn ; 49 vis[k] = true ; 50 for(int j = 1 ; j <= n ; j++){ 51 if(!vis[j] && dis[j] > mp[k][j]) 52 dis[j] = mp[k][j] ; 53 } 54 } 55 return ans ; 56 } 57 58 int main(){ 59 while(cin>>n && n){ 60 for(int i = 1; i <= n ;i++){ 61 cin>>cir[i].x>>cir[i].y>>cir[i].z>>cir[i].r; 62 } 63 memset(mp,0,sizeof(mp)); 64 for(int i = 1; i < n; i++){ 65 for(int j = i+1; j <= n ;j++){ 66 if(dist(cir[i],cir[j]) < eps){ 67 mp[i][j] = mp[j][i] = 0; 68 } 69 else{ 70 mp[i][j] = mp[j][i] = dist(cir[i],cir[j]); 71 } 72 } 73 } 74 /* 75 for(int i = 1; i <= n; i++){ 76 for(int j = 1 ; j <= n ;j++){ 77 cout<<mp[i][j]<<" "; 78 } 79 cout<<endl; 80 }*/ 81 double ans = prim(); 82 if(ans != -1){ 83 printf("%.3lf ",ans); 84 } 85 86 87 } 88 89 90 return 0; 91 }