題:
您是空間站工程團隊的成員,在空間站的建造過程中被配置設定了一項任務。您需要編寫一個計算機程式來完成該任務。
空間站由許多單元組成,稱為單元。所有的細胞都是球形的,但它們的大小不一定是一緻的。在空間站成功進入軌道後不久,每個單元就固定在預定位置。奇怪的是,兩個細胞可能互相接觸,甚至可能重疊。在極端情況下,一個單元可能完全封閉另一個單元。我不知道這樣的安排是怎麼可能的。
所有的單元都必須連接配接起來,因為機組成員應該能夠從任何一個單元走到任何其他單元。如果(1)A和B彼此接觸或重疊,(2)A和B通過“走廊”連接配接,或者(3)有一個C單元,這樣從A到C以及從B到C都可以從A單元步行到另一個B單元。請注意,條件(3)應進行傳遞性解釋。
您需要設計一個配置,即哪對單元将與走廊連接配接。在走廊配置中有一些自由。例如,如果有三個單元格A、B和C,彼此不接觸或不重疊,則至少可以有三個計劃來連接配接所有三個單元格。第一個是修建A-B和A-C走廊,第二個是B-C和B-A走廊,第三個是C-A和C-B走廊。修建走廊的成本與其長度成正比。是以,應選擇走廊總長度最短的平面圖。
可以忽略走廊的寬度。在兩個單元表面上的點之間建立一條走廊。它可以任意長,但當然要選最短的。即使兩條走廊A-B和C-D在空間上相交,也不認為它們在(例如)A和C之間形成連接配接路徑。換句話說,您可能認為兩條走廊從未相交。
輸入
輸入由多個資料集組成。每個資料集的格式如下。
N号
x1 y1 z1 r1型
x2 Y2 Z2 R2型
……
Xn-yn-zn-rn型
資料集的第一行包含整數n,即單元格數。n為正,不超過100。
以下n行是對單元格的描述。一條直線上的四個值是圓心的x、y和z坐标,以及球體的半徑(問題的其餘部分稱為r),順序如下。每個值都由一個小數點給出,小數點後有3位數字。值由空格字元分隔。
x、y、z和r中的每一個都是正的,小于100.0。
輸入的結尾由包含零的行訓示。
輸出
對于每個資料集,應列印走廊的最短總長度,每一條都單獨列印。列印的值應在小數點後3位。誤差不得大于0.001。
請注意,如果不需要走廊,也就是說,如果所有單元都沒有走廊連接配接,則走廊的最短總長度為0.000。
題解:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include <iostream>
#include <stack>
using namespace std;
#define MaxInt 0x3f3f3f3f
#define N 110
//建立map二維數組儲存圖表,low數組記錄每2個點間最小權值,visited數組标記某點是否已通路
double map1[N][N],low[N],visited[N];
int n,pos=1;
int w=0;
double prim()
{
int i,j,pos;
double min1,result=0;
memset(visited,0,sizeof(visited));
//從某點開始,分别标記和記錄該點
visited[1]=1;
pos=1;
//第一次給low數組指派
for(i=1; i<=n; i++)
//if(i!=pos)
low[i]=map1[pos][i];
//再運作n-1次
for(i=1; i<n; i++)
{
//找出最小權值并記錄位置
min1=MaxInt;
for(j=1; j<=n; j++)
if(visited[j]==0&&min1>low[j])
{
min1=low[j];
pos=j;
}
//最小權值累加
result+=low[pos];
//标記該點
visited[pos]=1;
//更新權值
for(j=1; j<=n; j++)
if(visited[j]==0&&low[j]>map1[pos][j])
low[j]=map1[pos][j];
}
return result;
}
int main()
{
double x[909],y[909],z[909],r[909],d=0;
int i,j,F;
double ans;
int t;
double v[9999],re=0;
memset(v,0,sizeof(v));
while(scanf("%d",&n)&&n)
{
//所有權值初始化為最大
t=1;
F=n;
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
{
if(i==j)
map1[i][j]=0;
else
map1[i][j]=MaxInt;
}
//cout<<w<<endl;
for(i=1; i<=n; i++)
{
scanf("%lf%lf%lf%lf",&x[i],&y[i],&z[i],&r[i]);
}
for(i=1; i<=n; i++)
{
//scanf("%lf%lf%lf%lf",&x[i],&y[i],&z[i],&r[i]);
//cout<<v[i]<<endl;
for(j=1+i; j<=n; j++)
{
d=(double)sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])+(z[i]-z[j])*(z[i]-z[j]));
d=d-r[i]-r[j];
if(d<=0)
d=0;
map1[i][j]=map1[j][i]=d;
}
}
re=prim();
printf("%.3lf\n",re);
}
return 0;
}