让我们假设我们有一架飞机上有一些点。 我们也有一个给定半径的圆。
我需要一种算法来确定圆圈的位置,它可以覆盖最大可能的点数。当然,有很多这样的位置,所以算法应该返回其中一个。
精度并不重要,算法可能会犯很小的错误。
这是一个示例图片:
输入:
int n
(n <= 50) - 点数;
float x[n]
和float y[n]
- 带有点X和Y坐标的数组;
float r
- 圆的半径。
输出:
float cx
和float cy
- 圈子中心的坐标
算法的闪电速度不是必需的,但它不应该太慢(因为我知道这种情况的一些慢速解决方案)。
C ++代码是首选,但不是强制性的。
答案 0 :(得分:18)
按照建议编辑更好的措辞:
基本观察:
然后算法:
答案 1 :(得分:6)
这是文献中的“磁盘部分覆盖问题” - 应该为您提供一个开始使用Google搜索的好地方。这是一篇涵盖一种可能解决方案的论文,但数学上有点强烈:http://www.utdallas.edu/~edsha/papers/bin/ISPAN04_cover.pdf
事实上,这属于称为计算几何的领域,这很有吸引力,但很难获得立足点。德贝格对与该主题相关的各种算法有很好的概述。
答案 2 :(得分:5)
如果你想要简单的东西,采取随机位置(x,y),计算圆内的点数并与之前的位置进行比较。取最大值。您可以随时重复此操作。
为什么地狱投票?有没有听过蒙特卡罗的方法?实际上对于大量的点,确定性算法可能无法在合理的时间内完成。
答案 3 :(得分:2)
问题还原为找到 f :R x R -> N
函数的全局最优。 f 的输入是圆的中心点,当然,该值是该组中包含的点的数量。功能图将是不连续的,类似楼梯的。
您可以从对应于集合中某个点的每个点测试函数开始,通过减少 f 的值来对点进行排序,然后加强围绕这些点的搜索(例如沿着螺旋)。
另一种选择是考虑连接集合中任何点对的所有交叉点。您的最佳点将位于我认为的其中一个交叉点,但它们的数量可能太大而无法考虑。
您也可以混合选项1和2,并考虑从“良好设定点”周围的点生成的线段的交叉点。
无论如何,除非设定点的数量很少(允许你检查所有的交叉点),我不会认为你可以保证找到最佳(只是一个很好的解决方案)。
答案 4 :(得分:1)
乍一看,我会说一个四叉树解决方案。
此外,还有一种名为K-means的信息可视化/数据挖掘方法,它可以生成给定数据的集群。它最终可以与附加功能一起使用,以满足您的目的。
K-Means的基本算法是:
添加的功能将是:
来源:
K均值算法 - Linköping University
四叉树 - en.wikipedia.org/wiki/Quadtree
快速搜索维基百科,找到源代码:en.wikipedia.org/wiki/K-means_clustering
答案 5 :(得分:1)
这有两个想法:O(n)近似算法和O(n ^ 2 log n)精确(非近似)算法:
快速近似
使用局部敏感散列。基本上,将每个点哈希到包含所有附近点的哈希桶。设置桶以便仅在附近点之间发生冲突 - 与类似命名的哈希表不同,冲突在这里很有用。保持存储桶中碰撞次数的运行计数,然后使用该存储桶的中心作为圆的中心。
我承认这是一个概念的快速解释,这个概念在您第一次听到它时并不是非常明显。一个类比是询问一群人他们的邮政编码是什么,并使用最常见的邮政编码来确定人口最多的圈子。它并不完美,但却是一种很好的快速启发式方法。
它在点数方面基本上是线性时间,你可以动态更新你的数据集,以每个点的恒定时间逐渐获得新的答案(相对于n =点的常数)
有关locality-sensitive hashes in general或约my personal favorite version that would work in this case的更多信息。
优于蛮力的确定性方法
这个想法是:对于每个点,将圆的边缘放在该点上并扫过圆圈以查看哪个方向包含最多的点。对所有点执行此操作,我们找到全局最大值
点p附近的扫描可以在n log n时间内完成:(a)找到每个其他点q的角度间隔,这样当我们将圆放置在角度θ时,它就包含q; (b)对间隔进行排序,以便我们可以在线性时间内围绕p进行行进/扫描。
因此,需要O(n log n)时间才能找到触及固定点p的最佳圆,然后将其乘以O(n)以执行所有点的检查。总时间为O(n ^ 2 log n)。
答案 6 :(得分:0)
如果确实精度不重要且算法可能会犯小错误那么我认为如下。
设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)
的最大值。
您可以从每个点开始使用渐变下降。
答案 7 :(得分:0)
我可以建议密度图吗?找到x和y的最小和最大边界。将x和y边界的范围划分为宽度等于圆的直径的bin。分别计算x和y的每个bin中的点数。现在在密度图上找到排名最高的x bin与排名最高的y bin之间的交点。
这是一种非常快速的算法,可以快速推广大型数据集,但并不总是准确的,为了提高准确性,您可以将垃圾箱切成更小更小的部分,或者将垃圾箱位置向左或向右移动n次并使用投票系统,用于选择试验间最常出现的答案。
答案 8 :(得分:0)
您可以对整个区域进行像素化,然后转到每个点并增加该点周围半径圆内的所有像素的值。总和最高的像素是很好的候选者。
当然,由于舍入误差,您可能会失去一些好的区域或“幻觉”好的区域。也许你可以先尝试粗略的像素化,然后改进有前景的区域。
答案 9 :(得分:-4)
这是着名的K最近点算法。这里描述:http://www.cs.ucsb.edu/~suri/cs235/ClosestPair.pdf