【问题标题】:Find two closest points in 2D distribution在二维分布中找到两个最近的点
【发布时间】:2020-05-01 08:08:01
【问题描述】:

我正在寻找一种算法来找到二维点列表中最近的两个点(每个点都有一个 x 和 y 属性)。

一种比蛮力更好的方法是将空间量化为重叠的块(沿着 2D 卷积的线)并蛮力计算每个块内的距离。

也就是说,我认为也许对 kd-trees 或高维索引(例如为创建近似最近邻查找树而生成的排序)了解更多的人可能是解决此问题的更好方法,所以我想问一下:

是否有智能/已知算法可以有效计算(2D)分布中最近的两个点?其他人在这方面可以提供的任何建议都会非常有帮助!

【问题讨论】:

  • 对我来说,这看起来像是寻路算法的工作。
  • 如果你想找到多个点之间的最短路径(3个或更多)我不认为有一个非常快速的算法,我相信你在谈论Traveling salesman problem
  • 谢谢!有没有更聪明的方法可以在线性时间内运行?我觉得量化确实可能是一种非常快速的技术
  • 恕我直言,这仅在您的数据没有歪斜并且您可以以某种方式猜测足够的框大小时才有效。首先构建分层索引结构可以为您解决这些问题,但也会花费 O(N log N)

标签: algorithm geometry kdtree


【解决方案1】:

经典的分治法在 O(n log(n)) 时间内起作用。 https://en.wikipedia.org/wiki/Closest_pair_of_points_problem

仔细查看 Note 3,并寻找 Rabin 算法。

【讨论】:

    【解决方案2】:

    这是竞争性编程中众所周知的问题。 这是我的实现。

    #include <iostream>
    #include <algorithm>
    #include <utility>
    #define x first
    #define y second
    #define INF 100000000
    
    using namespace std;
    
    int n;
    
    typedef pair<int, int> point;
    
    point tab1[100000];
    point tab2[100000];
    
    long long distance(point a, point b){
        return abs(a.x - b.x) + abs(a.y - b.y);
    }
    
    long long closestpair(int p, int k){
        if(p == k){
            return INF;
        }
        if(k - p == 1){
            return distance(tab1[p], tab1[k]);
        }
        int mid = (p + k) / 2;
        int count = 1;
        long long dl = closestpair(p, mid - 1);
        long long dp = closestpair(mid, k);
        long long len = min(dl, dp);
    
        for(int i = p; i <= k; i++){
            if(abs(tab1[i].x - tab1[mid].x) <= len){
                tab2[count] = make_pair(-tab1[i].y, tab1[i].x);
                count++;
            }
        }
        sort(tab2 + 1, tab2 + count + 1);
        for(int i = 1; i < count; i++){
            for(int j = i + 1; j < min(7, count - 1); j++){
                len = min(len, distance(tab2[i], tab2[j]));
            }
        }
        return len;
    }
    
    int main(){
        cin >> n;
        for(int i = 1; i < n + 1; i++){
            cin >> tab1[i].x >> tab1[i].y;
        }
        sort(tab1 + 1, tab1 + n + 1);
        cout << closestpair(1, n);
        return 0;
    }
    
    
    

    我找到了一些解释here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-25
      • 2019-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多