zoukankan      html  css  js  c++  java
  • POJ2031 Building a Space Station【最小生成树】

    题意:

    就是给出三维坐标系上的一些球的球心坐标和其半径,搭建通路,使得他们能够相互连通。如果两个球有重叠的部分则算为已连通,无需再搭桥。求搭建通路的最小边长总和是多少。

    思路:

    先处理空间点之间的距离,要注意的是两个球面相交的情况,相交的话距离是0。两球面距离是球心距离减去两个球的半径(边权 = AB球面距离 = A球心到B球心的距离 – A球半径 – B球半径),相交时距离是算出来是负值,要改为0。其实就是求连接所有球最小生成树的过程。

    代码:

    kruskal:

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    
    int n;
    double need;
    
    struct Station    //定义球的结构体
    {
        double x,y,z;
        double r;
    };
    Station station[110];
    
    struct Vdge    //构造生成树的点
    {
        int x,y;
        double l;
    };
    
    bool cmp(Vdge a,Vdge b){
        return a.l < b.l ;
    }
    
    Vdge edge[5500];
    int road[110];
    
    int find(int x)
    {
        while( x != road[x] )
            x = road[x];
        return x;
    }
    
    bool judge(int x,int y){
        int fx = find(x);
        int fy = find(y);
        if( fx==fy )
            return false;
        else
        {
            road[fx] = fy;
            return true;
        }
    }
    
    double dis(int i,int j)
    {
        double distance;
        double a = pow(station[i].x-station[j].x , 2);
        double b = pow(station[i].y-station[j].y , 2);
        double c = pow(station[i].z-station[j].z , 2);
        distance = sqrt(a+b+c);
        distance -= station[i].r + station[j].r;
        if( distance <= 0 ) distance = 0;
        return distance;
    }
    
    void init()
    {
        for(int i=0 ; i<n ; i++)
            scanf("%lf %lf %lf %lf",&station[i].x,&station[i].y,&station[i].z,&station[i].r);
        for(int i=0 ; i<n ; i++)
            road[i] = i;
        need = 0;
        int k = 0;
        for(int i=0 ; i<n ; i++)
        {
            for(int j=0 ; j<n ; j++)
            {
                if( j>i )
                {
                    edge[k].x = i;
                    edge[k].y = j;
                    edge[k].l = dis(i,j);
                    k++;
                }
            }
        }
        sort(edge,edge+n*(n-1)/2,cmp);
    }
    
    void kruskal()
    {
        int i=0,j=0;
        while( i<n-1 )
        {
            if( judge(edge[j].x,edge[j].y) )
                need += edge[j].l , i++;
            j++;
        }
    }
    
    int main()
    {
        while(cin>>n,n)
        {
            init();
            kruskal();
            printf("%.3f
    ",need );
        }
        return 0;
    }
    View Code
  • 相关阅读:
    使用批处理bat作为日期系统日期的前三天
    电脑桌面显示倒退
    BZOJ 2648/2716(SJY把件-KD_Tree)[Template:KD_Tree]
    yii使用寻呼功能
    宝付额度
    vs2010旗舰版产品密钥
    考察网贷平台是否正规,仅供参考。
    sql server 修改字段大小
    帕累托分析法
    帕累托分析法(Pareto Analysis)(柏拉图分析)
  • 原文地址:https://www.cnblogs.com/darklights/p/7637078.html
Copyright © 2011-2022 走看看