HDU 1007 (最近点对+qsort对结构体的排序!!!)

http://acm.hdu.edu.cn/showproblem.php?pid=1007

这题需要注意的有两点:

一:题目本身,做的思路是分治,像快速排序那样,把所有的点分成差不多的两段,然后再分……直至只剩2个或三个,那样就可以直接算了。

算法流程:

1:进入递归过程:如果是该段点数不大于三,那么就可以直接算了,否则用分治法递归解决

2:将大于四的这堆点分成两部分,得到最小的距离d。但这个距离还不能确定是最小的min,因为有可能一点p在左边,一点q在右边,而他们的距离有可能比d还小,是真正的min

3:将这堆实现按x排好序的点分成两部分,左边标志L,右边标志R,两个值不同。遍历左边的,找到所有距离中间这个点p[middle].x不超过d的,存在temp里

再遍历右边的,找到同样符合条件的点存在temp里。

4.遍历temp,穷举符合条件的点,不断更新min的值,这样的点不超过8过,《编程之美》里有解说。

5:返回min

二:贡献N次wa后才发觉可能是排序有问题,早知道就手搓了

ac代码

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#define L -1
#define R 1
typedef struct node
{
    int flag;//标志在左边还是右边
    double x,y;
}point;
point p[1000100],temp[1000100];//point存储点信息,minx存储x-d~x+d的点,miny则存储y-d~y+d的点
int cmpx(const void *a, const void *b)
{
    point *pa = (point *) a;
    point *pb = (point *) b;
    if (pa->x > pb->x)
        return 1;
    else if (pa->x < pb->x)
        return -1;
    else
        return 0;
}

int cmpy(const void *a, const void *b)
{
    int *pa = (int *) a;
    int *pb = (int *) b;
    if (temp[*pa].y > temp[*pb].y)
        return 1;
    else if (temp[*pa].y < temp[*pb].y)
        return -1;
    else
        return 0;
}
double minp(double a,double b)
{
    return a>b?b:a;
}
double distance(point a,point b)
{
    return sqrt(pow(a.x-b.x,2.0)+pow(a.y-b.y,2.0));
}
double getmindistance(int left,int right)
{
    double temp1,temp2,temp3,mindistance;
    int j=0,k=0,i,middle;
    if(left==right)
        return 0;
    else if(left+1==right)
        return distance(p[left],p[right]);//两个点
    else if(left+2==right)
    {
        temp1=distance(p[left],p[left+1]);
        temp2=distance(p[left+1],p[right]);
        temp3=distance(p[left],p[right]);
        return minp(minp(temp1,temp2),temp3);//三个点
    }
    else {
    middle=(left+right)/2;
    temp1=getmindistance(left,middle);
    temp2=getmindistance(middle+1,right);
    mindistance=minp(temp1,temp2);
    for(i=left;i<=middle;i++)
    {
        if(p[middle].x-p[i].x<=mindistance)
        {
            temp[j].flag=L;
            temp[j].x=p[i].x;
            temp[j].y=p[i].y;
            j++;
        }
    }
    for(;i<=right;i++)
    {
        if(p[i].x-p[middle].x<=mindistance)
        {
            temp[j].flag=R;
            temp[j].x=p[i].x;
            temp[j].y=p[i].y;
            j++;
        }
    }
    //qsort(temp,j,sizeof(temp[0]),cmpy);这里的排序是按另一种做法时才用到的
    for(i=0;i<j;i++)
       for(k=1;(k<8)&&(i+k<j);k++)
       {
           if(temp[i].flag!=temp[i+k].flag)
              mindistance=minp(distance(temp[i],temp[i+k]),mindistance);
       }
       return mindistance;
    }
}
int main()
{
    int n,i;
    double answer;
    while(scanf("%d",&n),n)
    {
        for(i=0;i<n;i++)
          {
              scanf("%lf%lf",&p[i].x,&p[i].y);
              p[i].flag=0;
          }
        qsort(p,n,sizeof(p[0]),cmpx);//先按x排序
        answer=getmindistance(0,n-1);
        printf("%.2lf\n",answer/2.0);//题目要求的是半径
    }
    return 0;
}
View Code

 

 

 

posted @ 2013-08-22 20:11  执着追求的IT小小鸟  阅读(217)  评论(0编辑  收藏  举报