【问题标题】:What type of problem is this? Help categorise这是什么类型的问题?帮助分类
【发布时间】:2021-02-11 02:25:28
【问题描述】:

最近,我遇到了这个问题,我很想知道 1) 我可以将这种类型的问题归类为一个特定的名称,或者 2) 解决这个问题的最佳方法是什么。这有点挑剔,所以请多多包涵,因为我会尽力解释它(为糟糕的绘图提前道歉)。

给定一个代表土壤图的 n x n 矩阵。每个条目都有一个数值,表示使该地块肥沃所需的水量。您可以选择降雨的特定坐标(强度I),降雨面积取决于参数d(始终是偶数) .大 d 意味着更大的面积..

这里是挑剔的部分。

下雨的方式如下图所示。郊区(由虚线绿线表示)的降雨量(I/2)是其对应地区的一半。所以在这种情况下,它将接收 4 毫米。因此,通过决定在点 (3,3) 周围倾盆大雨,边界上将有 7 块土壤(7 块小于或等于 8 / 2 = 4)和内部( 10 个小于或等于 8 的地块)导致总共 17 个土壤变得肥沃。

问题提出,给定 (n x n: 2d int array, d: int, I: int) 的参数,什么是可以肥沃的土壤的最大数量?

n.b.坐标的位置没有限制,即可以在地形的边缘。

我通过以下方式解决了它:

基本上是蛮力,但有一些效率调整。

效率调整 1:根据 d 的值,它包含多少块土壤有一个限制 [d * (d / 2 + 1)]。如果任何点满足最大值,则停止搜索。

效率调整 2:例如,如果 d 的值为 10,那么它的半径将为 5,这意味着它最多会在内部区域内完全覆盖 sqrt(5) 到 sqrt(5)。换句话说,它最多会完全覆盖 2 x 2,因此,我们可以从点 (2, 2) 开始搜索,而不是从 (0, 0) 开始搜索,这会造成不必要的水空地。类似地,我们可以在对角的对角点结束搜索,即 (n - 2, n - 2)。

这个解决方案感觉不是最佳的,因为随着 dn x n 变大,正在计算的土地有很多重叠。

【问题讨论】:

  • “这是什么类型的问题?帮助分类” - 这是一个优化问题。这真的是你要问的吗?
  • 顺便说一下,你不应该把它标记为 [java] 或 [kotlin] 因为你(有?)使用的实现语言是不相关的。据我所知。 (如果您向我们展示了代码,并提出了一个关于代码的问题,那么其中一个可能是相关的。但不是两者兼而有之。Java 和 Kotlin 是不同的语言。)跨度>
  • @StephenC 我希望它属于一个更具体的问题系列......如果我能找到类似的问题也很好。我使用递归来区分内部和外部级别,但我从未见过像这样的问题。我只是想了解更多关于这个问题的信息。。
  • 因此,如果您希望得到与我给出的答案不同的答案(顺便说一句,这是一个有效的答案),那么您的问题需要更清晰、更明确。 (你最好在scicomp.stackexchange.comcs.stackexchange.com 上问这个问题)
  • 正式注明。请记住,我问了两个问题。也去掉了标签,干杯。

标签: algorithm


【解决方案1】:

蛮力解决方案的时间复杂度为 O(n^2 * d^2)。

有效的优化是使用sliding window 方法。一旦您知道给定点的灌溉值,您就可以通过查看两个区域不同的正方形来计算下一个相邻点的值。这使您可以将复杂度降低到 O(n^2 * d)。

实际上,通过利用问题的几何特性,您可以进一步优化这种方法,以实现最优的 O(n^2) 时间复杂度。 (提示:考虑沿对角线移动窗口。)细节留给读者作为练习。

进一步阅读:

【讨论】:

  • 我不确定这实际上是否合理,因为在某些情况下,从角落开始(整个区域不在网格内)更有意义。例如,想象一个 n x n,其中左上角的值为 0,其他地方的值为 +Infinity。要么 1)你开始进入网格足够远以至于你错过了解决方案,要么 2)你从角落开始,在这种情况下滑动窗口方法不起作用
  • @220284 基本思想是,当您在网格上滑动窗口时,您只需要查看与前一个窗口的差异。您可能需要一些额外的边界条件逻辑,但这不应该影响渐近时间复杂度。我建议查看我的答案中的链接以了解一般方法,然后考虑如何将其应用于此问题的具体情况。
【解决方案2】:

如果边界单元接收到全部降雨量,问题会简单得多。在这种情况下,您可以将问题转换为滑动窗口 2D 最大子数组问题:

  1. 对于所有单元格,减去降雨量。
  2. 将可育细胞标记为 1,将非可育细胞标记为 0。
  3. 在生成的二进制矩阵上求解滑动窗口二维最大子数组问题。

该区域不是矩形并且边界单元仅接收一半降雨的事实使问题变得更加困难,但我仍然将此问题归类为最大子阵列问题的变体,并且在该空间中研究算法将是一个很好的起点。

【讨论】:

  • 好的,有什么关于遍历坐标的技巧吗?请注意,如果我指的是坐标 (1,1),它实际上是指数组中特定的土壤图,因为数组实际上并没有值之间的“坐标”的概念。我没有添加实现细节,但我这样做的方式是从原点 (0, 0) 周围的一组点开始,我会根据点的位置在必要时翻译这些点。我发现这真的很乏味和挑剔。想知道有没有更好的方法。另外,感谢您删除重复项。
  • 我绝对可以理解您必须将坐标转换为相应的数组[x][y] 项目的痛苦,反之亦然。处理一个接一个(或者在这种情况下一个接一个?)和这样的边缘情况总是很挑剔和乏味的,不幸的是我不知道有什么技巧可以让这个过程更容易。
【解决方案3】:

假设您有一个表格dp[][],其中dp[i][j] = 矩阵的i 行中value < I 的单元格数,在[0..j] 列之间(如何填充dp 表格:@987654327 @)。对于您给定示例的第一行,dp 表将显示为{1,2,3,4,5,5} 给定一行中的边界点,您可以使用此表在 O(1) 中计算该行中可育细胞的数量。

现在,如您的示例所示,您可以使用简单的观察。对于给定的d,有最大的(d-1)*4 边界点。考虑左侧的(d-1)*2 点(对于每个左边界点,同一行中将有一个右边界点)。对于该集合中的任何给定点x,(让它的正确对应点为y),您可以使用dp[][] 表获得@9​​87654335@ 和y 之间的肥沃细胞数量(具有全强度降雨) (count of fertile cells = dp[i][y]-dp[i][x], where i is the row number)。现在,您还要检查xy 本身是否因I/2 下雨而肥沃。

由于有N^2点,并且每个点都有O(d)边界点,因此这种方法将具有O(N^2 * d)时间复杂度和O(N^2)空间复杂度

【讨论】:

  • 对不起,我不明白这篇文章。您能解释一下如何填写 dp[][] 中的值吗?给定示例图像,我认为二维数组的第一行是 {1, 2, 3, 4, 5, 5} 是否正确?另外,我不知道我们如何在任何地方使用对称性?
  • 是的,我想我明白你的意思了。它是否类似于 augurar 所说的仅在第二次通过 2D 强度矩阵计算边界的想法(第一次,创建 2D dp 数组,第二次仅读取值)。另外,您是否同意他所说的可以在 O(n^2) 时间内完成?
  • @220284 我不确定 O(N^2),因为那会是很多预计算
猜你喜欢
  • 2010-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多