我有一组 n 点集,其中每个点集最多包含 m 点。
我想从每个点集中选择一个点,以便得到的点的选择尽可能接近。 (其中“亲密度”具有合理的定义,例如距所选点集的质心的平方距离之和。)
例如,输入集合可以是:
Point Set A: [(2, 1), (1, 2), (6, 5)]
Point Set B: [(1, 1), (7, 3)]
Point Set C: [(3, 7), (5, 3)]
我想选择三个点,每个点集合一个点,这些点最接近。在这个例子中,左下角的三个点最接近,但它们不包括C点。这里的解是右边的点:(6,5),(7,3),和(5,3)。它们围绕着它们的质心聚集在(6,3⅔)。
蛮力算法尝试集合中每个可能的点组合,并跟踪“接近度”函数的最小值(即 O(m ^ n)算法),但我想知道是否有一种更有效的方法可以扩展 n 和 m 的大值 - 如果不是在最坏的情况下,那么至少对大多数输入而言。
更新:这些点的实际值为坐标;上面使用整数来简化示例。
答案 0 :(得分:3)
首先,我们可以考虑对蛮力算法进行改进。
O(m ^ n)是一个巨大的数字!我们怎样才能增强这种搜索? 您没有搜索保证最低限度的集合的全局覆盖。 此外,每个集合的一个点都需要在解决方案中。 你是新的强力算法看起来像这样:
对于 S0 中的eache point p ,找到 S1中 p 的最近点 ... S(N-1)
此算法的计算复杂度为 O(m n m)
我们可以进一步改善我们的算法吗?的是
我们可以采用Kd-Tree加速邻居搜索。基本上你需要在O(m log(m))中构建 n Kd-Tree并使用它们将平均情况下的复杂度降低到 O(m 的的n * log(M))强>
这个算法总能找到最小值吗? 否强>
看看这个例子的广告:
正如您所看到的,使用先前算法获得的簇间距离不是最佳的,它只是最近邻启发式算法。好消息是你将接近解决方案。您可以采用Random-restart hill climbing algorithm来查找全局最小值
答案 1 :(得分:1)
你可以使用点的Delaunay三角剖分。该三角测量的图形编码接近信息:每个顶点通过Delaunay三角剖分的边缘连接到其最近的邻居。你可以使用Delaunay三角剖分和union-find来创建你的点集。
答案 2 :(得分:1)
可以将其视为combinatorial optimization问题。解决这个问题的一种方法是通过保持当前最佳点集来构建树并对树的每个分支进行DFS检查(称为Branch and Bound)。以下是您的示例的说明:
你沿着最左边的分支找到第一个结果。然后,每次你走下一个分支,如果在某个时刻你计算的距离优于你的实际结果,你可以停止对分支的探索 - 你不会通过下降获得更好的结果。
这可能与几点无关,但如果你有10组10分,这是一个很好的方法。加速过程的一种简单方法是将最小的集合放在树的顶部(减少节点和分支)。
显然,在最坏的情况下,最右边的分支是最好的分支。但是每个连续的分支都比前一个分支更好,所以你仍然应该获得一些时间。
注意:不要忘记在计算它时存储两点之间的距离,这样您就不必在以后重做微积分。