【问题标题】:finding largest region with small difference more efficiently更有效地找到差异较小的最大区域
【发布时间】:2020-07-23 04:35:37
【问题描述】:

有一个由 h * w (h, w 一个连续的区域是这样定义的:

  1. 给定一个点 P(x, y),连接区域必须包含这个点。
  1. 存在值为v的参考点R(x, y),连通区域中的任何点都必须与该点相连。此外,还有一个值 g_critical(g_critical

问题是找出最大连通区域的大小。

例如网格。 h = 5, w = 5, g_critical = 3, P(x, y) = (2, 4)

1 3 7 9 2
2 5 6 6 8
3 5强> 9 3 6
2 7 3 2 9

在这种情况下,粗体区域是最大的连接区域。请注意,在这种情况下,在 (2, 3) 或 (2, 2) 处选择了 R(x, y)。区域大小为 14。

我稍微改写了这个问题,所以它更短。因此,如果有任何歧义,请在评论中指出。这个问题也在我们的私人法官中,所以我无法在这里分享问题来源。

我的尝试

我尝试循环遍历每个单元格,将其视为 R 点并使用 bfs 查找连接到它的连接区域。然后,检查 P 是否包含在该区域中。

复杂度是O(h * h * w * w),太大了。那么有什么办法可以优化呢?

我猜也许以 p 开头会有所帮助,但我不知道该怎么做。也许有某种洪水填充算法可以让我这样做?

提前致谢。

【问题讨论】:

  • g_critical 有多大?对于小 g 值和大矩阵大小,简单的方法就是检查从 P-g 到 P+g 的可能中间值(所以 O(hwg))
  • g_critical 最高可达 100000
  • 太多了,所以这种方式不合适。
  • 我不认为这是这些数字的最大区域。如果您选择 R(x,y) 作为 (3,2) 或 (4,2) (是的,与 P 相同 - 这是被禁止的吗?)。您似乎从 3..9 得到 15 个数字。
  • @Hans 你说得对,我稍后再编辑

标签: algorithm grid graph-algorithm breadth-first-search flood-fill


【解决方案1】:

有一个 O(h w √(g_critical) α(h w)) 时间算法(其中 α 是反阿克曼函数,用于实际用途的常数),它使用具有“撤消”操作和变体的不相交集数据结构莫的诡计。这个想法是,将区间 [v - g_critical, v] 分解为长度约为 √g_critical 的约 √g_critical 子区间。对于每个子区间 [a, b],准备一个不相交的集合数据结构,表示允许值为 [b, a + 2 g_critical] 的矩阵分量。然后对于 [a, b] 中的每个 c,用其值位于 [c, b) 和 (a + 2 g_critical, c + 2 g_critical] 的点扩展不相交集,并报告 P( x,y),然后撤消这些操作(保留对结构所做的写入堆栈,使用原始值;然后弹出每个,写入原始值)。

还有一个你不会喜欢的 O(h w log(h w)) 时间算法,因为它使用动态树。 (Sleator–Tarjan 1985 年基于伸展树的构造是最简单的,在这里工作正常。)发布它主要是为了以防它激发更实用的方法。

高级思想是一种动力学算法,它在最多 g_critical + 1 个可能性上“滑动”允许值的区间,重复报告并在包含 P 的连接组件的大小上取最大值。

为此,我们需要在派生图上维护最大生成森林。给定一个节点加权无向图,通过细分每条边并将每条新边的权重设置为它所关联的旧节点的权重,构造一个新的边权重图。删除图中最轻的节点很简单——如果可能,所有路径都会避开这些节点,因此新的最大生成森林将不再有任何边。要添加不在图中的最轻节点,请尝试一次链接它们的入射边。如果形成一个循环,则翻转一个端点,从另一个端点查询路径最小值,然后取消链接该最小值。

要报告包含 P 的组件的大小,我们需要另一个修饰来捕获每个节点的具体子树(而不是表示的子树)的大小。细节有点粗糙。

【讨论】:

    【解决方案2】:

    这里有一些可能会有所帮助的启发式方法:

    首先在O(h*w*log(h*w))进行一些预处理:

    • 将矩阵值存储在数组中,对其进行排序
    • 现在数组中的每个值都可能是点 R 的候选对象
    • 最大分量也将是 [R-critical, R+critical] 范围内的值
    • 因此我们可以通过简单的二分搜索来估计组件的大小(在最佳情况下)

    现在一些启发式方法:

    • 这次再次按估计的组件大小降序对数组进行排序
    • 如果估计大小大于当前找到的最佳大小,现在按此顺序尝试 BFS

    【讨论】:

    • 这个如果以后通过我会尝试,但我怀疑有更好的方法
    • 我已经尝试过了,但仍然超出了时间限制。我猜最坏情况的复杂度仍然是 O(h * h * w * w) 因为估计的组件大小可能比实际大小大得多。那么目前找到的最佳尺寸总是小于估计的尺寸。
    • 您使用什么语言?使用 C++ O(h*h*w*w) 大约是 1.6 * 10^9 操作,所以它应该在 2 秒内工作,编译时使用 -OFast 或 atleasy -O3 优化甚至更快(您可以在代码中添加带有 #pragma 选项的那些`
    • 我正在使用 C++,我需要它在 1 秒内工作
    • 有些学生以 0.073 秒的运行时间完成它,所以必须有一些更复杂的方法
    猜你喜欢
    • 2023-03-09
    • 2013-03-14
    • 1970-01-01
    • 2021-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-07
    • 1970-01-01
    相关资源
    最近更新 更多