• Building a Space Station


    Building a Space Station poj-2031

        题目大意:在一个三维平面内,给出n个球,我想把两个球连起来,使得两两之间联通,连起来的代价是两个球的球心距减去半径之和。如果两球相切或相交,则代价是0。

        注释:n<=100,坐标以及半径是double。

          想法:我们首先两个球之间的距离的运算规则Dist。运算之后我们暴力枚举每两个球之间的距离,并将他们存入到单独的边得结构体里。然后,将点的编号设为1-n,即可。最后,由于两两联通,我们用kruskal算法求最小生成树即可。

        最后,附上丑陋的代码... ...

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <algorithm>//C-Free时默认开全库的...蜜汁CE 
     5 #define N 110
     6 using namespace std;
     7 double x[N],y[N],z[N],r[N];
     8 int fa[N];
     9 struct Node
    10 {
    11     int a;
    12     int b;
    13     double val;
    14 }f[N*N];//由于我们f数组记录的是边的数量,所以要开到n*n。 
    15 bool cmp(Node a,Node b)
    16 {
    17     return a.val<b.val;
    18 }
    19 int find(int x)
    20 {
    21     return fa[x]==x?x:(fa[x]=find(fa[x]));
    22 }
    23 inline bool merge(int x,int y)
    24 {
    25     x=find(x),y=find(y);
    26     if(x==y)return 0;
    27     fa[x]=y;return 1;
    28 }
    29 inline double Dist(int a,int b)//运算Dist 
    30 {
    31     double ans;
    32     ans=sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b])+(z[a]-z[b])*(z[a]-z[b]));
    33     if(ans<=r[a]+r[b]) return 0;
    34     else return ans-r[a]-r[b];
    35 }
    36 int main()
    37 {
    38     int n;
    39     int cnt=0;
    40     while(1)
    41     {
    42         scanf("%d",&n);
    43         if(n==0) return 0;
    44         cnt=0;
    45         for(int i=1;i<=n;i++)
    46         {
    47             scanf("%lf%lf%lf%lf",&x[i],&y[i],&z[i],&r[i]);
    48         }
    49         for(int i=1;i<=n;i++) fa[i]=i;
    50         for(int i=1;i<=n;i++)
    51         {
    52             for(int j=i+1;j<=n;j++)
    53             {
    54                 f[++cnt].a=i;
    55                 f[cnt].b=j;
    56                 f[cnt].val=Dist(i,j);
    57             }
    58         }
    59         sort(f+1,f+cnt+1,cmp);//这步很重要,别问我是怎么知道的... 
    60         int count=0;
    61         double ans=0;
    62         for(int i=1;i<=cnt;i++)//kruskal
    63         {
    64             if(merge(f[i].a,f[i].b))
    65             {
    66                 ans+=f[i].val;
    67                 count++;
    68             }
    69             if(count==n-1) break;
    70         }
    71         printf("%.3lf
    ",ans);
    72     }
    73 }

        小结:kruskal算法比较的方便,虽然这是prim算法的课后练习题。

          错误:1.C-Free是默认开全库的,我排序的时候忘记开algorithm库了...

             2.由于这是一个选择的代价最小问题,我们可以清楚地发现这是没有误解情况的。

             3.kruskal必须保证每条边被存了且只被存了一次。

  • 相关阅读:
    java环境变量的配置
    usb转串口驱动时会出现“文件的哈希值不在指定的目录”这样的提示
    虚拟机安装tools for Ubuntu
    ubuntu 修改root密码
    旺旺自动回复
    android 启动流程
    ASCII 码表
    电脑中快速查找东西
    appengine 云计算。 部署web网络。
    openssl-0.9.8k_WIN32(RSA密钥生成工具
  • 原文地址:https://www.cnblogs.com/ShuraK/p/8289724.html
Copyright © 2020-2023  润新知