我在一组中有一组相当大的2D点(~20000),并且对于x-y平面中的每个点,想要确定该组中哪个点最接近. (实际上,这些点的类型不同,我只想知道哪种类型最接近.而x-y平面是位图,比如640×480.)
从this answer到问题“All k nearest neighbors in 2D, C++”我有了制作网格的想法.我创建了n * m个C向量并将这些点放在向量中,具体取决于它落入哪个bin.这个想法是你只需要检查垃圾箱中的点的距离,而不是所有的点.如果垃圾箱中没有任何点,则以螺旋方式继续相邻的垃圾箱.
不幸的是,我之后只阅读了Oli Charlesworth的评论:
Not just adjacent, unfortunately (consider that points in the cell two
to the east may be closer than points in the cell directly north-east,
for instance; this problem gets much worse in higher dimensions).
Also, what if the neighbouring cells happen to have less than 10
points in them? In practice, you will need to “spiral out”.
幸运的是,我已经找到了螺旋式代码(一个不错的C++ version here,并且在同一个问题中还有其他版本).但我还是留下了这个问题:
>如果我在一个单元格中找到一个点击,相邻单元格中可能会有更接近的点击(黄色是我的探测器,红色是错误的选择,绿色是实际的最近点):
>如果我在相邻的小区中发现一个命中,那么在2步之外的小区中可能会有一个命中,正如Oli Charlesworth所说:
>但更糟糕的是,如果我在两步之外的一个牢房中发现一次撞击,那么在三步之外的撞击中仍然会有更接近的击中!这意味着我必须考虑所有具有dx,dy = -3 … 3或49个细胞的细胞!
现在,实际上这不会经常发生,因为我可以选择我的bin大小,以便细胞足够填充.不过,我希望得到一个正确的结果,而不是迭代所有点.
那么如何找出何时停止“螺旋式”或搜索?我听说有一种方法有多个重叠的网格,但我不太明白.是否有可能挽救这种网格技术?
最佳答案 由于位图的尺寸不大,并且您想要计算每个(x,y)的最近点,因此可以使用动态编程.
设V [i] [j]是从(i,j)到集合中最近点的距离,但只考虑集合中“矩形”[(1,1)中的点,(i, j)的].
如果(i,j)中有一个点,或者V [i] [j] = min(V [i’] [j’] dist((i,j),则V [i] [j] = 0, (i’,j’)))其中(i’,j’)是(i,j)的三个邻居之一:
即
>(i – 1,j)
>(i,j – 1)
>(i – 1,j – 1)
这为您提供了最小距离,但仅适用于“左上角”矩形.我们对“右上”,“左下”和“右下”方向做同样的事情,然后采取最小值.
复杂度为O(平面的大小),这是最佳的.