给定一组2D点X,我想找到一个包含最多n个点的凸包。当然,这并不总是可能的。因此,我正在寻找由max。最多覆盖X点集合的n个点。
更正式地表示,如果F(H,X)返回凸包H覆盖的X点的数量,其中| H |是构建船体的点数,然后求出以下数量:
H_hat = argmax_H F(H,X),s | t | H | <= n
解决该问题的另一种方法是查找包含max。集合X的n个角,使其最大程度地覆盖了集合X。
我提出的方法如下:
fetchFeesList(studentID){
val res = it.result
if(res){
toast("success")
}else {
toast("failure")
}
}
但是,这是一种非常慢的方法。我有很多点,而n(约束)很小。这意味着原始的凸包包含很多点,因此while循环会循环很长时间。有更有效的方法吗?还是有其他建议来解决这个问题?
答案 0 :(得分:2)
一些想法。
删除顶点时要排除的点位于该顶点和凸包上与其相邻的两个顶点形成的三角形中。删除任何其他顶点不会影响可能排除的点的集合。因此,我们只需为每个删除的顶点重新计算覆盖率两次。
说到重新计算的覆盖范围,我们不必一定要关注每一个问题。这个想法并不能改善最坏的情况,但是我认为这在实践中应该是一个很大的改进。保持以下各项的指数。选择一个随机顶点作为“根”,并将由根和其他两个顶点形成的三角形包含它们的点分组(采用良好算法的O(m log m)时间)。每当我们删除非根顶点时,我们都会对涉及已删除顶点的三角形的两个点集进行合并和过滤。每当我们重新计算覆盖率时,我们都只能扫描两个相关三角形中的点。如果我们曾经删除过这个根,请选择一个新的根并重做索引。预期的总维护成本为O(m log ^ 2 m),其中m是点数。不过,很难估算出计算覆盖率的成本。
如果点在船体内合理地均匀分布,则可以使用区域作为覆盖的代理。将顶点存储在优先级队列中,该优先级队列由它们的邻居(耳朵)形成的三角形区域排序。每当我们删除一个点时,都要更新其两个相邻点的耳朵区域。这是一种O(m log m)算法。
答案 1 :(得分:1)
以下方法可能对您有用:最初,计算凸包H
。然后从n
中随机选择H
个点的子集,这将构造一个可能不覆盖所有点的新多边形,因此我们将其称为准凸包Q
。计算Q
(内部)中包含的点数。重复此操作一定次数,并使Q
建议书的内线最多。
这似乎与RANSAC有关,但是对于此任务,我们实际上并没有什么是离群值的概念,因此我们无法真正估计离群率。因此,我不知道这种近似将有多好,或者您需要多少次迭代才能得到一个合理的结果。也许您可以添加一些启发式方法,而不是单纯地随机选择n
点,或者您可以设置一个阈值,确定至少应包含在Q
中的点数,然后在达到该阈值时停止。
修改
实际上,在考虑之后,您可以使用RANSAC方法:
max_inliers = 0
best_Q = None
while(true):
points = sample_n_points(X)
Q = construct_convex_hull(points)
n_inliers = count_inliers(Q, X)
if n_inliers > max_inliers:
max_inliers = n_inliers
best_Q = Q
if some_condition:
break
这样做的好处是,凸包的创建比您的方法更快,因为它最多使用n
点。另外,检查内部线的数量应该很快,因为它可以与凸包的每条腿进行一堆符号比较。
答案 2 :(得分:1)
以下内容无法按照我提出的方式解决问题,但是可以解决产生问题的问题。因此,我想添加它,以防其他人遇到类似的情况。
我研究了两种方法:
1)将凸包视为多边形,并对其应用多边形简化算法。我研究的特定算法是Ramer-Douglas-Peucker Algorithm。
2)应用问题中描述的算法,而无需重新计算凸包。
就我所知,这两种方法都无法为您提供理想的解决方案,但是对于我的任务来说,它们运行得很好。