【问题标题】:Algorithm to cover maximal number of points with one circle of given radius用一个给定半径的圆覆盖最大点数的算法
【发布时间】:2011-03-14 20:30:49
【问题描述】:

假设我们有一个平面,上面有一些点。 我们还有一个给定半径的圆。

我需要一种算法来确定圆的位置,使其覆盖最大可能的点数。当然,这样的位置很多,所以算法应该返回其中一个。
精度并不重要,算法可能会犯一些小错误。

这是一个示例图片:

输入:
int n (n float x[n]float y[n] – 具有点 X 和 Y 坐标的数组;
float r – 圆的半径。

输出:
float cxfloat cy – 圆心坐标

算法的闪电速度不是必需的,但不应该太慢(因为我知道一些针对这种情况的慢速解决方案)。

C++ 代码是首选,但不是强制性的。

【问题讨论】:

  • 你对积分的分配没有限制?
  • 这听起来很棒codegolf
  • @bobobobo 我真的不这么认为。很无聊,没有确切的获胜条件……但请随意提出这样的问题。

标签: c++ algorithm geometry points


【解决方案1】:

按照建议修改为更好的措辞:

基本观察:

  • 我假设半径是 1,因为它不会改变任何东西。
  • 给定任意两点,它们所在的单位圆上最多存在两个单位圆。
  • 为您的问题提供一个解决方案圈,您可以移动它直到它包含您的集合中的两个点,同时在其中保持您的集合中相同数量的点。

那么算法是:

  • 对于每对点,如果它们的距离
  • 计算你的集合在 C1 和 C2 内的点数
  • 尽最大努力。

【讨论】:

  • 我喜欢这个解决方案。它可能是我需要的……但我不确定它是否总是正确的
  • 你能解释一下 Alex 的基本原理吗?
  • 点数是O(n^3)。您可以通过计算我认为的一个行列式来检查 C 是否在通过 A 和 B 的半径为 1 的圆内(具有一个规定的方向)。但请注意舍入错误,它们真的会破坏这种算法。
  • 我没有注意到你的回答:(,写的完全一样,有点解释。
  • @IVlad:对于每两个相距 正好相距 2r,则只有一个圆。)关于这两个点,这些圆是“最佳的”:由于这些点位于圆的边界上,因此圆覆盖最大的额外空间(可能还有更多点)。遍历所有点对会为您提供所有可能的圆,其中 >= 2 个点。检查这些圆圈中每个圆圈包含的点数,然后选择数字最高的一个圆圈。
【解决方案2】:

这是文献中的“磁盘部分覆盖问题”——它应该为您提供一个开始谷歌搜索的好地方。这是一篇涵盖一种可能解决方案的论文,但它在数学上有点紧张:Approximation Algorithms Design for Disk Partial Covering Problem

事实上,这属于称为计算几何的领域,这很吸引人,但很难站稳脚跟。deBerg 对与该主题相关的各种算法进行了很好的概述。

【讨论】:

  • 我觉得算法不能用在这种情况下,因为我只有一个圈
  • 在你的情况下,论文的“k”是1。
【解决方案3】:

如果您想要一些简单的东西,请随机取 (x,y) 位置,计算圆内的点数并与之前的位置进行比较。取最大值。随时重复该操作。

为什么要投反对票?听说过蒙特卡洛方法吗?实际上对于大量的点,确定性算法可能无法在合理的时间内完成。

【讨论】:

  • @maxwellb:“精度不重要,算法可能会犯一些小错误”
  • 合理时间也用与给定点数的关系来表示。例如,O(n^3) 表示算法完成的时间与点数的立方成正比。通常,算法的“合理”时间是:多项式(n^3,n^8,n^k):OK,线性(n,或 3n,(1/9)n,kn,都是 n):很好,对数:太棒了。
  • 很公平,我认为你的观点是正确的,所以我没有投反对票。干杯。
  • 对于我的情况,这个解决方案还不错
  • 一个好的蒙特卡洛算法可以将错误概率绑定为某个参数的函数(例如,在您的情况下,迭代次数)。我在您的解决方案中没有看到任何此类分析。
【解决方案4】:

这里有两个想法:一个 O(n) 近似算法和一个 O(n^2 log n) 精确(非近似)算法:

快速逼近

使用局部敏感散列。基本上,将每个点散列到包含所有附近点的散列桶中。桶的设置使得冲突只发生在附近的点之间——与名称相似的哈希表不同,冲突在这里很有用。记录一个桶中的碰撞次数,然后以该桶的中心为圆心。

我承认这是对一个概念的快速解释,当你第一次听到它时,它并不是很明显。一个类比是问一群人他们的邮政编码是什么,并使用最常见的邮政编码来确定人口最多的圈子。它并不完美,但却是一种很好的快速启发式方法。

就点数而言,它基本上是线性时间,您可以即时更新您的数据集,以在每个点的恒定时间内(相对于 n = 点数恒定)逐步获得新答案。

更多关于locality-sensitive hashes in general或关于my personal favorite version that would work in this case的信息。

优于蛮力的确定性方法

这个想法是:对于每个点,将一个圆的边缘放在那个点上,然后将圆扫一圈,看看哪个方向包含的点最多。对所有点执行此操作,我们会找到全局最大值。

可以通过以下方式在 n log n 时间内完成围绕点 p 的扫描: (b) 对区间进行排序,以便我们可以在线性时间内围绕 p 行进/扫掠。

因此需要 O(n log n) 时间来找到接触固定点 p 的最佳圆,然后将其乘以 O(n) 以执行所有点的检查。总时间为 O(n^2 log n)。

【讨论】:

    【解决方案5】:

    问题回到寻找函数f:R x R -> N全局最优值。 f 的输入是圆的中心点,值当然是集合中包含的点数。该函数的图形将是不连续的,类似楼梯的。

    您可以首先在与集合中的一个点对应的每个点中测试函数,通过减小 f 的值对这些点进行排序,然后围绕这些点加强搜索(例如沿着螺旋)。

    另一种选择是考虑连接集合中任意点对的线段的所有个交点。我认为您的最佳点将位于这些交叉点之一,但它们的数量可能太大而无法考虑。

    您也可以混合选项 1 和 2,并考虑从“良好设置点”周围的点生成的线段的交点。

    无论如何,除非设定点的数量很少(允许您检查所有交叉点),否则我不认为您可以保证找到最佳值(只是一个好的解决方案)。

    【讨论】:

    • 我可以看到相同的答案总共发布了三遍 - 可能是错误的。你能删除它的两个实例吗?
    • 完成。 SO技术问题:-)
    • 分数很低(我刚刚编辑了问题)。但我不明白一些事情,比如......你怎么能制作一个 2 参数函数的图表?
    • 离散值函数的最小化是非常困难的。
    • @Philipp 好吧,我认为在一般情况下,实际上只有线性(非整数)是易于处理的。但我们离题了:-)
    【解决方案6】:

    乍一看,我会说四叉树解决方案。

    此外,还有一种称为 K-means 的信息可视化/数据挖掘方法,它可以对给定数据进行聚类。它最终可以与附加功能一起使用,以满足您的目的。

    K-Means 的基本算法是:

    1. 将 K 点放入项目所代表的空间中 正在聚类的 - 这些点代表初始组质心
    2. 将每个数据项分配给最接近的组 质心
    3. 分配完所有项目后,重新计算 通过计算点的平均位置来计算 K 质心的位置
    4. 重复第 2 步和第 3 步,直到质心不再移动或移动很少

    添加的功能将是:

    1. 计算圆内位于 K 质心的点数
    2. 选择最适合您的一款 ;)

    来源:
    K-means 算法 - Linköping University
    四叉树 - en.wikipedia.org/wiki/Quadtree

    在维基百科上快速搜索,您会找到源代码:en.wikipedia.org/wiki/K-means_clustering

    【讨论】:

      【解决方案7】:

      如果确实精度并不重要并且算法可能会犯一些小错误,那么我认为如下。

      f(x,y) 是一个在点 (0,0) 处有最大值且仅在半径为 R 的圆内的点处有效的函数。例如,f(x,y) = e^{(x^2 + y^2)/ (2 * R^2)}

      (x_i,y_i) 为点,E_i(x,y) = f(x - x_i, y - y_i)

      你的问题是找到\sum_i E_i(x,y)的最大值。

      您可以使用从每个点开始的梯度下降。

      【讨论】:

      • 我是 15 岁的孩子。我喜欢编程,但我不喜欢数学。所以我经常不明白这些聪明的数学东西:)
      • @BlaXpirit,如果你不太懂数学,你可以通过编程获得很多成就。但是要有效地解决和理解您发布的任务的解决方案,您应该在数学方面做得更好。 (顺便说一句,Alexey 也在使用 LaTeX 表示法来编写数学函数,它与数学无关,但您最好了解其中之一)
      • @Alexey,如果f1 inside the circle, and 0 outside,那将是绝对正确的。 :-)
      • @Pavel,对于不可微函数的情况,梯度下降无法正常工作。
      • @Pavel,我也敢肯定。我以If it is true that precision is not important... 开始回答。
      【解决方案8】:

      我可以推荐一张密度图吗?找到 x 和 y 的最小和最大界限。将 x 和 y 边界的范围划分为宽度等于圆直径的箱。分别计算 x 和 y 的每个 bin 中的点数。现在在密度图上找到排名最高的 x bin 与排名最高的 y bin 之间的交集。

      这是一种非常快速的算法,可以快速泛化大型数据集,但它并不总是准确的,为了提高准确性,您可以将 bin 切成越来越小的块,或者将 bin 位置向左或向右移动 n 次,然后使用投票系统来选择试验之间最常出现的答案。

      【讨论】:

      • 我有非常小的数据集,而不是大数据集。所以这里不正确
      【解决方案9】:

      您可以对整个区域进行像素化,然后转到每个点并增加围绕该点的半径圆内所有像素的值。总和最高的像素是很好的候选。

      当然,由于舍入误差,您可能会丢失一些好的区域或“幻觉”好的区域。或许您可以尝试先进行粗略的像素化,然后细化有希望的区域。

      【讨论】:

        【解决方案10】:

        这是著名的 K-最近点算法。此处描述:http://www.cs.ucsb.edu/~suri/cs235/ClosestPair.pdf

        【讨论】:

        • 不,不是。你可以有一个以集合的一部分为中心的最佳圆。
        • 你现在做 :-) 继续问有趣的问题!
        • @BlaXpirit 如果答案不正确,请取消选择它作为已接受的解决方案。
        猜你喜欢
        • 2014-01-17
        • 1970-01-01
        • 1970-01-01
        • 2014-05-12
        • 1970-01-01
        • 2012-05-25
        • 1970-01-01
        • 1970-01-01
        • 2011-04-25
        相关资源
        最近更新 更多