最近点对

#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#define INF 100000000
#define N 100000

struct 
{
    double x;
    double y;
}point[N];

int temp[N];

int cmpy(const void * y1, const void * y2) //根据y坐标进行排序
{
    if(*(double *)y1 < *(double *)y2)
        return 1;
    return 0;
}

int cmpxy(const void *index1, const void *index2)
{
    if(fabs(point[*(int *)index1].x - point[*(int *)index2].x) > 1e-3)  //如果x坐标不同
        if(point[*(int *)index1].x < point[*(int *)index2].x) //根据x坐标排序
            return 1;
    else//x坐标相同的情况下,根据y坐标排序
    {
        if(point[*(int *)index1].y < point[*(int *)index2].y)
            return 1;   
    }
    return 0;
}

double dist(int index1, int index2)  //计算点index1和点index2的距离
{
    double dx = fabs(point[index1].x - point[index2].x);
    double dy = fabs(point[index1].y - point[index2].y);
    double d = dx*dx + dy*dy;
    return sqrt(d);
}

double min(double a, double b)
{
    return a<b?a:b;
}

double cloest_pair(int left, int right) 
//返回点区间上最近两点间的距离,
//left为区间最左边的点,right为最右边的点
{
    double d = INF;
    if(right == left)   //如果只有一个点
        return d;
    else if(right == left+1)  //如果只有两个点
        return dist(left, right);  //如果有三个及以上的点
    else
    {
        int mid = (left+right)>>1;  //取区间中点
        double d1 = cloest_pair(left, mid);  //d1=左半区间最近点距离
        double d2 = cloest_pair(mid+1, right);  //d1=右半区间最近点距离
        d = min(d1, d2);  
        int i, j, k=0;
        //以左半区间和右半区间的垂直分割线为中心,分离出宽度为d的区间
        for(i=left; i<=right; i++)
        {
            if(fabs(point[i].x-point[mid].x)<=d/2)
                temp[k++] = i;
        }
        qsort(temp, k, sizeof(int), cmpy);  //将距离d之内的点按y坐标排序
        //对y坐标线性扫描
        for(i=0; i<=k; i++)
        {   //对于x坐标在宽度为d的区间内的每个点,y坐标在宽度为2d之内
            for(j=i+1; j<k && fabs(point[temp[j]].y-point[temp[i]].y)<d; j++)
            {  
                double d3 = dist(temp[i], temp[j]);
                if(d3<d)
                    d = d3;  //更新最短距离
            }
        }
    }
    return d;
}

int main()
{
    int len;
    int i, k;
    printf("输入点对个数:");
    scanf("%d", &len);
    printf("输入各点:\n");
    for(i=0; i<len; i++)
    {
        printf("x=");
        scanf("%lf", &point[i].x);
        printf("y=");
        scanf("%lf", &point[i].y);
    }
    qsort(point, len, sizeof(point[0]), cmpxy);
    double d = cloest_pair(0, len-1);
    printf("最短距离为:%lf\n", d);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值