其他分享
首页 > 其他分享> > 计算几何——平面最接近点对

计算几何——平面最接近点对

作者:互联网

 计算几何使人秃头,求平面最接近点对即在一个平面中有 n n n 个点,求这 n n n 点的最接近的两个点之间的距离,在洛谷上看,有大佬说旋转加排序(然鹅为啥要选择),个人觉得这个做法是不正确的,很容易被一些数据卡住。

正解的话应该是分治求解,首先将平面上点按照 x x x 轴分成左右均分的两部分 s 1 , s 2 s_1,s_2 s1​,s2​,那么对于最近的距离只有两种可能,

1. 1. 1. 两个点都在一个区域内, s 1 s_1 s1​或者 s 2 s_2 s2​。

2. 2. 2. 两个点一个在 s 1 s_1 s1​中,一个在 s 2 s_2 s2​中。

基于上面的过程我们可以对其进行分治求解,知道出现区域内只剩下一个点和两个点的情况

1. 1. 1. 只剩一个点,返回 I N F INF INF

2. 2. 2. 只剩两个点,返回这两个点之间的距离

t h e   c o d e the\space code the code

#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 1000001;
const int INF = 2 << 20;
int n, temp[maxn];
struct Point
{
    double x, y;
} S[maxn];
bool cmp(const Point &a, const Point &b)
{
    if(a.x == b.x) return a.y < b.y;
    else return a.x < b.x;
}
bool cmps(const int &a, const int &b) { return S[a].y < S[b].y; }
double min(double a, double b) { return a < b ? a : b; }
double dist(int i, int j)
{
    double x = (S[i].x - S[j].x) * (S[i].x - S[j].x);
    double y = (S[i].y - S[j].y) * (S[i].y - S[j].y);
    return sqrt(x + y);
}
double merge(int left, int right)
{
    double d = INF;
    if(left == right) return d;
    if(left + 1 == right) return dist(left, right);
    int mid = (left + right ) >> 1;
    double d1 = merge(left, mid);
    double d2 = merge(mid + 1, right);
    d = min(d1, d2);
    int i, j, k = 0;
    for(i = left; i <= right; i++)
        if(fabs(S[mid].x - S[i].x) < d) // 这里不太一样
            temp[k++] = i;
    sort(temp, temp + k, cmps);
    for(i = 0; i < k; i++)
        for(j = i + 1; j < k && S[temp[j]].y - S[temp[i]].y < d; j++)
        {
            double d3 = dist(temp[i], temp[j]);
            if(d > d3) d = d3;
        }
    return d;
}
int main()
{
    scanf("%d", &n);
    for(int i = 0; i < n; i++) scanf("%lf%lf", &S[i].x, &S[i].y);
    sort(S, S + n, cmp);
    return !printf("%.4lf\n", merge(0, n - 1));
}

标签:right,return,int,double,const,几何,平面,接近,left
来源: https://blog.csdn.net/weixin_50187215/article/details/120341667