题:
您是空间站工程团队的成员,在空间站的建造过程中被分配了一项任务。您需要编写一个计算机程序来完成该任务。
空间站由许多单元组成,称为单元。所有的细胞都是球形的,但它们的大小不一定是一致的。在空间站成功进入轨道后不久,每个单元就固定在预定位置。奇怪的是,两个细胞可能相互接触,甚至可能重叠。在极端情况下,一个单元可能完全封闭另一个单元。我不知道这样的安排是怎么可能的。
所有的单元都必须连接起来,因为机组成员应该能够从任何一个单元走到任何其他单元。如果(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;
}