问题

二维平面上的n个点,不存在完全重叠的两个点。请找出最接近的两个点之间的距离。

代码

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;

struct point
{
    double x, y;
}p[100005];

int a[100005]; 

int cmpx(const point& a, const point& b)
{
    return a.x < b.x;
}
int cmpy(int& a, int& b)
{
    return p[a].y < p[b].y;
}
inline double dis(point& a, point& b)
{
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
inline double min(double a, double b)
{
    return a < b ? a : b;
}
double closest(int low, int high)
{
    if (low + 1 == high)
        return dis(p[low], p[high]);
    if (low + 2 == high)
        return min(dis(p[low], p[high]), min(dis(p[low], p[low + 1]), dis(p[low + 1], p[high])));
    int mid = (low + high) >> 1;
    double ans = min(closest(low, mid), closest(mid + 1, high)); 
    int i, j, cnt = 0;
    for (i = low; i <= high; ++i) 
    {
        if (p[i].x >= p[mid].x - ans && p[i].x <= p[mid].x + ans)
            a[cnt++] = i;      
    }
    sort(a, a + cnt, cmpy); 
    for (i = 0; i < cnt; ++i)
    {
        for (j = i + 1; j < cnt; ++j)
        {
            if (p[a[j]].y - p[a[i]].y >= ans)
                break;
            ans = min(ans, dis(p[a[i]], p[a[j]]));
        }
    }
    return ans;
}
int main(void)
{
    int i, n;
    while (scanf("%d", &n) != EOF)
    {
        if (!n)
            break;
        for (i = 0; i < n; ++i)
            scanf("%lf", &p[i].x);
        for (i = 0; i < n; ++i)
            scanf("%lf", &p[i].y);
        sort(p, p + n, cmpx);
        printf("%.4lf\n", closest(0, n - 1));
    }
    return 0;
}

样例

  最接近的点对为(90.46,8.07)和(91.64,38.22),距离为30.1731。 对于30%的数据,n ≤1000, 对于100%的数据 n ≤50000,坐标值均 ≤100000 。

输入

  • 第一行为一个正整数n。 第二行为n个数,表示n个点的横坐标。 第三行为n个数,表示n个点的纵坐标。
6
13.43 37.40 78.76 91.64 90.46 57.83
10.76 75.48 99.56 38.22 8.07 20.02

输出

  • 最接近的两个点的欧式距离(保留四位有效小数)
30.1731
最后修改:2022 年 09 月 19 日
如果觉得我的文章对你有用,请随意赞赏