例如,您有一个0和1的矩阵:
1 1 1 0
1 1 1 0
1 1 1 0
1 1 1 1
0 1 1 1
1 0 1 1
将一个正方形放置在位置(0,0),找到从左上角到右下角移动的所有1的最大正方形的大小。广场只能向下和向右移动,只能在1的元素上移动。
在这个例子中,最大正方形的大小是2.正方形中元素的索引是(0,0),(0,1),(1,0),(1,1)。
我不确定如何解决这个问题。我想首先,你需要找到左上角的所有方块和右下角的所有方块。如果移动是可能的,则这两个位置必须有相同大小的正方形。然后只尝试将左角的大小相等的方块移动到右角的方形。但我不确定如何找到方块并检查它们是否可以移动。
答案 0 :(得分:1)
您可以使用动态编程。
我们假设max_size(i, j)
是可以留在(i, j)
单元格中的最大正方形的大小(可能为0)(保持在其左上角是位于这个单元格中)。我们可以以天真的方式计算这个值(通过迭代地增加正方形的大小并检查它是否与任何0
无关)。如果天真的解决方案不可行,我们可以对答案和前缀总和使用二进制搜索,以便每个单元格获得O(log n)
个时间。
让我们说f(i, j)
是可以到达(i, j)
单元格的最大正方形。基本情况:f(0, 0) = max_size(0, 0)
(我们总是可以到达左上角)。对于其他单元格,可以通过以下方式计算(我在这里省略了极端情况):
for i <- 0 ... n - 1:
for j <- 0 ... m - 1:
f(i, j) = min(max_size(i, j), max(f(i - 1, j), f(i, j - 1)))
答案是最大f(i, j)
,i + f(i, j) - 1 = n - 1
和j + f(i, j) - 1 = m - 1
。
时间复杂度为O(n * m * log(min(n, m)))
。
答案 1 :(得分:0)
你的第一步是正确的:找到适合右下角和左上角的最大正方形。
然后,从左上方的那个大小的正方形开始。尝试右下角宽度优先的路径。在每个步骤之后,检查方块是否仍然适合,否则减小其大小。然后,您将经常从两个方向(从上方和左方)到达指定地点。继续从那里开始更大的规模(这个统一步骤就是为什么你应该进行广度优先,这也称为&#34;动态编程&#34;)。
在您的示例中,您从(0 0)
处的大小为2的数组开始,但是为了演示目的,我们假设您从大小3开始。因此,第0层是(0 0)
处大小为3的单个正方形。向下移动没有问题,但是在一些零上移动到正确的步骤,所以你必须减小尺寸。因此,第1层是两个正方形的列表:(1 0)
的大小为3,(0 1)
的大小为2。下一层:从(0 1)
向右移动,需要在(0 2)
缩小为1;向下移动(0 1)
以及从(1 0)
向右移动,两者都从{1}到达,从大小为2,从左边需要缩小到大小2,所以大小为2;向下移动(1 1)
,缩小为大小2.因此,第2层是三个正方形的列表:(1 0)
的大小为2,(2 0)
的大小为2的正方形之一(1 1)
的大小为1。我认为这足以作为示范。
完成包含触摸右下方的正方形的图层后,您已达到解决方案。当所有正方形的大小均为0时,您可以确定没有解决方案。
答案 2 :(得分:0)
如果您的矩阵的大小为N x M
,则从左上角到右下角的大小为S x S
的正方形的每个路径都是N + M - 2S
'步'(向右或向左移动)长,N - S
步骤将向下,M - S
步骤向右。因此,如果我们忽略矩阵上的值,将会有(N + M - 2S) choose (N - S)
个可能的路径。
因此,如果矩阵不是太大,则可以尝试针对给定的方形大小S
尝试所有这些路径,并测试它们是否符合方形放置规则(无论是在每个步骤中, square只包含1
s和0
s。)
为S
到1
的每个min(N,M)
执行此操作,并跟踪S
的值,您可以找到至少一个有效路径。
然后,只需取出这些S
值中的最大值,即可得到想要的结果。
所以暴力迫使(最终)会给你正确的价值。
当然,这不是那么高效,这将导致大型矩阵的大量运行时间。但我们可以通过研究哪些步骤是不必要的来逐步改进。
如果您找到了给定方块大小S
的有效路径,则不必为相同的方块大小寻找更多路径,并且可以跳过测试其他未经测试的方块大小。< / p>
如果路径的任何步骤导致无效展示位置,则您无需检查其他步骤。你已经知道你无法使用整条路径。
具有给定尺寸(N-S) * (M-S)
的正方形的S
个可能展示位置中的每一个都将成为多条路径的一部分。不是检查每个展示位置的有效性,而是为每个展示位置执行一次,并将结果存储在(N-S) x (M-S)
矩阵中。
如果您已经测试了给定方块大小S
的所有路径,并且它们都没有效果,那么您根本不必测试更大的S
,因为您知道赢了是他们的有效途径。
如果您找到了给定方形大小S
的路径,则可以确保所有较小的方块大小也至少有一个有效路径,因此您无需测试它们。 (无论如何,当你正在寻找具有至少一个有效路径的最大S
时,你不必这样做。)
结合上面的两个实现,您将得出结论:按顺序测试大小S
不是最佳的,无论是增加还是减少。相反,您可以从中间的某个位置开始,并根据S
的结果 - 排除S
的所有较小或全部较大的值。是否最适合在中间开始(min(N,M) / 2
),我不确定,作为搜索给定S
的路径数量(请记住二项式系数公式中的二项式系数公式)上面的“蛮力”部分)取决于S
的大小。
几乎每个级别的强力算法都有几个相互独立的步骤,可以并行执行。
我确信即使已经完成上述所有操作,即使我现在也想不到任何优化,仍然有更多优化空间。