poj-2031
題意:在一個三維空間裡建造球形的小室,若小室相鄰或部分重疊,或者間接有走廊間接相連,則兩個小室相連通,給出n個小室,下面n行每行分別是n個小室的球形空間座標,和球形小室的半徑長度。找出讓所有球形小室聯通所需要建造長廊的最短距離。
思路:相鄰兩球的距離用球心座標,和兩個球心半徑比較。二維陣列鄰接矩陣存圖,兩個小室之間所需要長廊的距離為兩點之間的權值,若相鄰,或重疊,權值為0,最小生成樹,找出最短路徑。
反思:struct 裡x,y,z都要是double型,minn存dis陣列,也是double型
//
// Created by xrm on 18-11-2.
//
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int maxn=105;
const int inf=0x3f3f3f3f;
double Graph[maxn][maxn];
double dis[maxn];
bool vis[maxn];
struct node{
double x,y,z,r;
}p[maxn];
int N;
double length(node a,node b){
double l;
l=(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z);
l=sqrt(l);
if(l-a.r-b.r<0)
return 0;
else{
return l-a.r-b.r;
}
}
double prim(){
double ans=0;
for(int i=0;i<N;i++){
dis[i]=Graph[0][i];
}
dis[0]=0;
vis[0]=1;
for(int i=1;i<N;i++){
int pos=-1;
double minn=inf;
for(int j=0;j<N;j++){
if(!vis[j]&&dis[j]<minn){
minn=dis[j];
pos=j;
}
}
vis[pos]=1;
ans+=minn;
for(int k=0;k<N;k++){
if(!vis[k]&&dis[k]>Graph[pos][k]){
dis[k]=Graph[pos][k];
}
}
}
return ans;
}
int main(){
while(cin>>N&&N){
double sum;
for(int i=0;i<N;i++){
scanf("%lf%lf%lf%lf",&p[i].x,&p[i].y,&p[i].z,&p[i].r);
}
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
if(i==j)
Graph[i][j]=0;
else
Graph[i][j]=inf;
}
}
for(int i=0;i<N;i++){
for(int j=i+1;j<N;j++){
sum=length(p[i],p[j]);
if(Graph[i][j]>sum)
Graph[i][j]=Graph[j][i]=sum;
}
}
memset(vis,0,sizeof(vis));
double dd;
dd=prim();
printf("%.3f\n",dd);
}
return 0;
}