http://poj.org/problem?id=2031
题意:你是空间站的一员,太空里有很多球形且体积不一的“小房间”,房间可能相距不近,也可能是接触或者甚至是重叠关系,所有的房间都必须相连,这样的话宇航员才能从这个房间走到另一个房间,而宇航员从一个房间走到另一个房间,只要满足三个条件中的一个即可:1两个房间是接触的,2两个房间是重叠的,3两个房间之间有走廊相连。也因此若是没有接触的两个小房间就要有走廊连接,忽略走廊的宽度,花费与长度成正比,所以当然是花费越少越好,而球与球之间的距离只接触到两球的表面即可,因为两球的表面相距最近,因此你的工作就是算给出的几个小房间中要达到相连的状态需花费的最小钱数是多少
思路:要求两个房间之间必须要有相连的走廊,所以就是最小生成树的思想,只要再考虑一下是不是接触或重叠就可以了
#include<cstdio> #include<iostream> #include<cmath> #include<algorithm> #include<cstring> using namespace std ; const double eps=1e-8 ; const int INF = 1<<28; struct point { double x,y,z,w ; point() {} point(double a,double b,double c,double d):x(a),y(b),z(c),w(d) {} }; inline double sqrt1(double a)//函数被调用的次数多了就比较浪费时间,所以可以定义成内置函数 { return a*a; } double dis(const point &a,const point &b)//求两点间距离 { return sqrt(sqrt1(a.x-b.x)+sqrt1(a.y-b.y)+sqrt1(a.z-b.z)); } double low[1000] ; double dist[110][110],ans ; bool vis[1000] ; int n ; int prim() { ans = 0 ; int i,j,flag; double minn ; for(i = 1 ; i <= n ; i++) { low[i] = INF ; vis[i] = false ; } low[1] = 0 ; for(i = 1 ; i <= n ; i++) { minn = INF ; flag = 0 ; for(j = 1 ; j <= n ; j++) { if(minn > low[j]&&!vis[j]) { minn = low[j] ; flag = j ; } } if(minn >= INF) return false ; ans += minn ; vis[flag] = true ; for(j = 1 ; j <= n ; j++) { if(!vis[j]&&low[j]>dist[flag][j]) low[j] = dist[flag][j] ; } } return true ; } int main() { while(scanf("%d",&n)&&n) { point a[1000]; memset(dist,0,sizeof(dist)); for(int i=1; i<=n; i++) scanf("%lf%lf%lf%lf",&a[i].x,&a[i].y,&a[i].z,&a[i].w); for(int i=1; i<=n; i++) { for(int j=1; j<=n; j++) { if(dis(a[i],a[j])-a[i].w-a[j].w<=0)//两球间最短距离为两球球心距离再减去两球的半径 dist[i][j]=0; else if(dis(a[i],a[j])-a[i].w-a[j].w>eps) dist[i][j]=dis(a[i],a[j])-a[i].w-a[j].w; } } prim(); printf("%.3lf ",ans); } return 0; }
特别郁闷的是明明是同一个代码,一开始交是0ms后来交就是16ms。。。。。