poj 2031 Building a Space Station(prim)
颓废了几天,开始努力~
题意:给出N个球体的球新坐标以及球的半径,让你求出连接这N个球的最短的隧道距离,其中相接触和相覆盖的两个球之间不由隧道。
思路:最小生成树,刚开始的想法是kruskal,但是看了discuss里的讨论,说prim更快些,所以就用了prim,不用排序的确更容易些。
代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <algorithm> #include <math.h> #define maxm 105 #define INF 0xffff using namespace std ; struct node { double x , y , z ; double rad ; }p[maxm] ; int f[maxm] ; double dis[maxm] ; double prim ( int a , int b ) { if ( p[a].x == p[b].x && p[a].y == p[b].y && p[a].z == p[b].y && p[a].rad == p[b].rad ) return 0.0 ; else { double xx = p[a].x - p[b].x ; double yy = p[a].y - p[b].y ; double zz = p[a].z - p[b].z ; double len = sqrt ( ( xx * xx ) + ( yy * yy ) + ( zz * zz )) ; if ( ( len- p[a].rad - p[b].rad ) <= 0.000001) return 0.0 ; else return ( len - p[a].rad - p[b].rad ) ; } return 0.0 ; } int main() { int i , j , k , n ; double s , len ; while ( scanf ( "%d" , &n ) , n) { memset( f , 0 , sizeof ( f )) ; for ( i = 0 ; i < n ; i++ ) { scanf ( "%lf%lf%lf%lf" , &p[i].x , &p[i].y , &p[i].z , &p[i].rad ) ; dis[i] = 1000.0 ; } for ( i = 1 ; i < n ; i++ ) { dis[i] = prim ( 0 , i ) ; } s = 0.0 ; f[0] = 1 ; for ( i = 1 ; i < n ; i++ ) { k = -1 ; double minn = INF * 1.0; for ( j = 1 ; j < n ; j++ ) { if ( dis[j] < minn && !f[j] ) { k = j ; minn = dis[j] ; } } if ( k > 0 ) { f[k] = 1 ; s += minn ; } for ( j = 0 ; j < n ; j++ ) { double len =prim ( k , j ) ; if ( len < dis[j] && !f[j] ) { dis[j] = len ; } } } printf ( "%.3lf\n" , s ); } return 0 ; }