分治法解决最小套圈问题

来源:互联网 发布:淘宝新品促销海报图 编辑:程序博客网 时间:2024/04/28 20:09

/*     Copyright    by ZhongMing-Bian     Jan,6,2010   */
/*             分治法解决最小套圈问题                  */
/*        Jan,11  debug ;input question                */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define  MAX_POINTS  100000    /*坐标点数的最大值 */
#define MAX_TEST 100     /*最大测试次数*/

typedef  struct  {    /*定义坐标点*/
    float  x;
    float  y;
}Point;


float  dist(Point  a,  Point  b)  {    /*求两个坐标点之间的距离*/
    return  sqrt((float)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
  }


float  Nearest(Point*  points,  int  n){   /*求最小距离*/
    float temp1,temp2,temp3,temp,nearest;
    float left,right,d;    /*当n小于4时,T(n)=O(1);*/
    int i,j;
    if(n==1)  return  999999999;             /*一个点情形,返回值模拟无穷*/
    if(n==2)  return  dist(points[0],  points[1]);  /*两个点情形*/
    if(n==3){                          /*三个点情形*/
        temp1=dist(points[0],  points[1]);
        temp2=dist(points[0],  points[2]);
        temp3=dist(points[1],  points[2]);
        return  temp3<((temp1<temp2)?temp1:temp2)?temp3:((temp1<temp2)?temp1:temp2);
        }
    /*多于3点的情形,用分治法*/
    left=Nearest(points,n/2);      /*递归求解*/
    right=Nearest(&points[n/2],n-n/2);
    d=left<right?left:right;
    /*综合中间带求得最小距离*/
    nearest=d;
    for(i=0;i<n/2;i++)
    /* 通过扫描子集一中每个点检查子集二中与其距离在d之内的
          所有点(最多6个)以完成合并*/
        for(j=n/2;j<n&&(fabs(points[j].y-points[i].y)<d);j++){
            temp=dist(points[i],points[j]);
            nearest=nearest<temp?nearest:temp;
            }
    return nearest;
}


int  compx(const  void*  a,  const  void*  b)  {
    /*实现按x排序*/
    return  ((Point*)a)->x-((Point*)b)->x;
}


int  compy(const  void*  a,  const  void*  b)  {
    /*实现按y排序*/
    return  ((Point*)a)->y-((Point*)b)->y;
}


void main() {
    int i,j=0,numPoints;
    Point  points[MAX_POINTS];
    float result[MAX_TEST];        /*记录结果*/
    for(i=0;i<MAX_TEST;i++)    result[i]=-1;
    printf("请输入数据:/n");
    while(1){                     /*进行多次测试*/
loop:   scanf("%d",  &numPoints);
        if(!numPoints) break;
        if(numPoints<0||numPoints>MAX_POINTS) {
            printf("Error!/n");       /*容错处理*/
            goto loop;
        }
        for(i=0;  i<numPoints;  i++)    /*输入点的数量及点的坐标值*/
            scanf("%f  %f",  &points[i].x,  &points[i].y);
         /*预排序,在使用分治法之前,预先将S中的n个点依其y坐标排序好。*/
        qsort(points, numPoints,  sizeof(Point),  compx);
        qsort(points, numPoints/2,  sizeof(Point), compy);
        qsort(points+numPoints/2,  numPoints-numPoints/2,  sizeof(Point), compy);
        result[j]=Nearest(points, numPoints)/2;
        j++;
        }
    i=0;
    printf("/n最短距离分别为:/n");
    while(result[i]!=-1)    /*输出测试结果*/
            printf("%.2f/n",result[i++]);
}

原创粉丝点击