[kuangbin带你飞]专题六 最小生成树C - Building a Space Station

曾经终败给现在 2023-08-17 15:41 218阅读 0赞

C - Building a Space Station

题目链接:https://vjudge.net/contest/66965#problem/C

题目:

您是空间站工程团队的成员,并在该站的施工过程中分配了一项任务。您需要编写一个计算机程序来完成任务。
空间站由许多单元组成,称为单元。所有细胞都是球形的,但它们的大小不一定是均匀的。在该站成功进入其轨道后不久,每个小区固定在其预定位置。很奇怪,两个细胞可能彼此接触,甚至可能重叠。在极端情况下,细胞可能完全包围另一个细胞。我不知道这样的安排是如何可能的。

  1. 所有细胞必须连接,因为机组成员应该能够从任何细胞走到任何其他细胞。如果,(1AB相互接触或重叠,(2AB通过“走廊”连接,或者(3)有一个单元格C,它们可以从单元格A走到另一个单元格B.从AC,从BC都是可能的。注意,条件(3)应该被传递解释。
  2. 您需要设计一个配置,即哪些单元格对与走廊连接。走廊配置有一些自由。例如,如果存在三个单元ABC,彼此不接触或不重叠,则至少三个计划是可能的,以便连接所有三个单元。第一个是建造走廊A-BA-C,第二个是B-CB-A,第三个是C-AC-B。建造走廊的成本与其长度成正比。因此,您应该选择走廊总长度最短的计划。
  3. 您可以忽略走廊的宽度。在两个单元格表面上的点之间构建一个走廊。它可以任意长,但当然选择最短的一个。即使两个走廊A-BC-D在空间相交,也不认为它们在(例如)AC之间形成连接路径。换句话说,您可以认为两条走廊从不相交。

输入
输入由多个数据集组成。每个数据集以下列格式给出。

  1. ñ
  2. x1 y1 z1 r1
  3. x2 y2 z2 r2
  4. ...
  5. xn yn zn rn
  6. 数据集的第一行包含整数n,即整数。 n是正数,不超过100
  7. 以下n行是细胞的描述。一行中的四个值是球体的中心的xyz坐标,以及球体中的半径(在问题的其余部分中称为r),按此顺序。每个值由小数部分给出,小数点后3位。值由空格字符分隔。
  8. xyzr中的每一个都是正的并且小于100.0
  9. 输入的结尾由包含零的线表示。

产量
对于每个数据集,应打印走廊的最短总长度,每个都在一个单独的行中。打印的值应在小数点后3位。它们可能没有大于0.001的误差。

  1. 请注意,如果不需要走廊,也就是说,如果所有单元都没有走廊连接,则走廊的最短总长度为0.000

样本输入

  1. 3
  2. 10.000 10.000 50.000 10.000
  3. 40.000 10.000 50.000 10.000
  4. 40.000 40.000 50.000 10.000
  5. 2
  6. 30.000 30.000 30.000 20.000
  7. 40.000 40.000 40.000 20.000
  8. 5
  9. 5.729 15.143 3.996 25.837
  10. 6.013 14.372 4.818 10.671
  11. 80.115 63.292 84.477 15.120
  12. 64.095 80.924 70.029 14.881
  13. 39.472 85.116 71.369 5.553
  14. 0

样本输出

  1. 20.000
  2. 0.000
  3. 73.834

思路:

  • 在三维空间中给你 n 个球体的坐标和半径
  • 如果这些球体间没有相通,则需要你去建立一些通道把所有的球体连接起来。
  • 表面相切即可认为相通。

  • 首先在各球体间建图,然后再按照边从小到大排序

  • 用并查集查找两点是否属于同一联通分量【即判断这条边的两个球是否相通】
  • 如果不属于同一联通分量,则连接即可
  • 由于每次都是找的最短的边,所以最终所求一定是最短距离了

    //
    // Created by hy on 2019/7/30.
    //

    include

    include

    include

    include

    include

    include

    include

    using namespace std;
    typedef long long ll;
    const int maxn=2e5+10;
    int n,m;
    struct Node{
    double x,y,z,r;
    }node[maxn];
    struct Edge{
    int u,v;
    double w;
    bool operator<(const Edge &other)const{

    1. return this->w<other.w;

    }
    }edge[maxn];
    int father[maxn];
    int find(int x)
    {
    if(x==father[x])

    1. return x;

    return father[x]=find(father[x]);
    }
    double len(Node L,Node R)
    {
    return sqrt((L.x-R.x)(L.x-R.x)+(L.y-R.y)(L.y-R.y)+(L.z-R.z)*(L.z-R.z));
    }
    double kru()
    {
    double ans=0;
    for(int i=0;i<m;i++)
    {

    1. int uu=find(edge[i].u);
    2. int vv=find(edge[i].v);
    3. if(uu==vv)
    4. continue;
    5. else
    6. {
    7. ans+=edge[i].w;
    8. father[uu]=vv;
    9. }

    }
    return ans;
    }
    int main()
    {
    while(~scanf(“%d”,&n))
    {

    1. if(n==0)
    2. break;
    3. for(int i=0;i<=n;i++)
    4. father[i]=i;
    5. for(int i=0;i<n;i++)
    6. scanf("%lf%lf%lf%lf",&node[i].x,&node[i].y,&node[i].z,&node[i].r);
    7. m=0;
    8. for(int i=0;i<n;i++)
    9. for(int j=i+1;j<n;j++)
    10. {
    11. edge[m].u=i;
    12. edge[m].v=j;
    13. edge[m].w=max(0.0,len(node[i],node[j])-node[i].r-node[j].r);
    14. m++;
    15. }
    16. sort(edge,edge+m);
    17. printf("%.3f\n",kru());

    }
    return 0;
    }

转载于:https://www.cnblogs.com/Vampire6/p/11272860.html

发表评论

表情:
评论列表 (有 0 条评论,218人围观)

还没有评论,来说两句吧...

相关阅读