POJ2031

来源:互联网 发布:淘宝密码忘了无法显示 编辑:程序博客网 时间:2024/05/17 07:39

Problem: Building a Space Station
Description: 给出三维坐标系上的一些球的球心坐标和其半径,搭建通路,使得他们能够相互连通。如果两个球有重叠的部分则算为已连通,无需再搭桥。求搭建通路的最小费用(费用就是边权,就是两个球面之间的距离),其实我也是百度的题意。
Solution: Prim。这里要注意的是有球是直接连通的。那么我们在处理这个map[from][to]的时候直接设为0,那么我们直接可以用这条路。
Code(C++):

#include <stdio.h>#include <string.h>#include <math.h>const int M=105;const double INF=0x3f3f3f3f;typedef struct tagCircle{    double x,y,z;    double r;}Circle;int n;Circle circles[M];double map[M][M];double dis[M];bool used[M];double distance2(Circle a,Circle b){    return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z);}double prim(){    double ans=0;    memset(used,false,sizeof(used));    for(int i=0;i<n;i++)        dis[i]=INF;    dis[0]=0;    for(int i=0;i<n;i++){        double tmp=INF;        int k=1;        for(int j=0;j<n;j++)            if(!used[j]&&tmp>dis[j])                k=j,tmp=dis[j];        if(tmp>=INF)            break;        ans+=tmp;        used[k]=true;        for(int j=0;j<n;j++)            if(!used[j]&&dis[j]>map[k][j])                dis[j]=map[k][j];    }    return ans;}int main(){    while(scanf("%d",&n),n){        for(int i=0;i<n;i++)            scanf("%lf%lf%lf%lf",&circles[i].x,&circles[i].y,&circles[i].z,&circles[i].r);        for(int i=0;i<n;i++)            for(int j=i+1;j<n;j++){                double d2=distance2(circles[i],circles[j]);                double r2=(circles[i].r+circles[j].r)*(circles[i].r+circles[j].r);                map[i][j]=map[j][i]=(d2>r2? sqrt(d2)-sqrt(r2):0);            }        double ans=prim();        printf("%.3f\n",ans);    }    return 0;}
0 0
原创粉丝点击