想看更多的解题报告: http://iyenn.com/rec/1824570.html
转载请注明出处:http://blog.csdn.net/wangjian8006
题目大意:给定一些个球的圆心与半径,如果两个球之间相交,则他们之间连通,否则不连通,问还需要连多长的边使所有球都连通
解题思路:一个已存在边的最小生成树,只不过题目太难读了,任意两个球,如果连通则边权为0,否则边权为d-r1-r2,d是两球圆心坐标之间的距离,r1与r2分别为两个球的半径,这样求一个最小生成树,将所有球连接起来
- /*
- Memory 280K
- Time 16MS
- */
- #include
- #include
- using namespace std;
- #define MAXV 105
- #define INF 10e8
-
- typedef struct{
- double x,y,z,r;
- }QIU;
-
- QIU q[MAXV];
- int n;
- double map[MAXV][MAXV];
-
- double distance(int i,int j){
- double x=q[i].x-q[j].x;
- double y=q[i].y-q[j].y;
- double z=q[i].z-q[j].z;
- return sqrt(x*x+y*y+z*z);
- }
-
- double cross(int i,int j){
- double r=q[i].r+q[j].r;
- double d=distance(i,j);
- if(d>r) return d-r;
- return 0;
- }
-
- void prim(){
- int i,j,v;
- double d[MAXV];
- bool vis[MAXV];
- for(i=1;i<=n;i++){
- d[i]=map[1][i];
- vis[i]=0;
- }
-
- for(i=1;i<=n;i++){
- double min=INF;
- for(j=1;j<=n;j++)
- if(!vis[j] && d[j]
//找最小点加进来 - min=d[j];
- v=j;
- }
-
- vis[v]=1;
-
- for(j=1;j<=n;j++){
- if(!vis[j] && map[v][j]
//取邻边的最小边 - d[j]=map[v][j];
- }
- }
- for(d[0]=0,i=1;i<=n;i++) d[0]+=d[i];
- printf("%.3lf\n",d[0]);
- }
-
- int main(){
- freopen("d:\\test.in","r",stdin);
- int i,j;
- while(~scanf("%d",&n) && n){
- for(i=1;i<=n;i++){
- scanf("%lf%lf%lf%lf",&q[i].x,&q[i].y,&q[i].z,&q[i].r);
- }
- memset(map,0,sizeof(map));
- for(i=1;i<=n;i++){
- for(j=i+1;j<=n;j++){
- map[i][j]=map[j][i]=cross(i,j);
- }
- }
-
- prim();
- }
- return 0;
- }
评论记录:
回复评论: