高效动态编程布尔矩阵中的矩形查询

时间:2014-01-07 15:08:42

标签: algorithm query-optimization dynamic-programming multidimensional-array

请有人建议使用动态编程方法来解决SPOJ问题“标准问题”,链接: - http://www.spoj.com/problems/ASTDPROB/

问题陈述: 给定一个大小为NXM的布尔矩阵。对于int low low,high类型的所有Q查询,找到最大区域子矩形,它只有零,位于编号为low和high的行之间。

1 ≤ N, M ≤ 1000 
1 ≤ Q  ≤ 10^6

我需要一个O(n ^ 2)或O(n ^ 2 * log n)dp算法。

直到我的方法如此

  1. 我使用DP预先计算最大子矩形的边,在几乎O(n ^ 2)的时间内开始每个单元格(i,j)。
  2. 将每个查询的答案存储在网格中[M] [M](目前我在O(n ^ 3)中进行操作= 1秒内大约10 ^ 9个原子操作,这是不可能的)
  3. 然后回答O(1)中的所有查询。
  4. 请为第2步建议任何优化?

    任何采用更有效方法的人,请分享一下。

    提前致谢。

1 个答案:

答案 0 :(得分:2)

M成为01 s的矩阵。

计算矩阵S,其中S[k][l]' is the number of consecutive zeros up from M [k] [l]`。这将需要O(n ^ 2)。

现在,对于给定的查询(lo,hi),您可以从第lo行转到第hi行。对于每一行line,按以下方式查找从linehi的最大矩形: - 通过p使用指针S[line]并跟踪可能的高度。

例如,假设S[line] = [1,2,2,1,5,6,9,2,1,4]。当p = 5你应该有一个元组列表,如:     W = [0,4,5] 从中你可以计算在p==6处完成的矩形的大小:

max(S[line][W[0]], hi-lo+1) * (p-W[0] + 1) = 6
max(S[line][W[1]], hi-lo+1) * (p-W[1] + 1) = 10
max(S[line][W[2]], hi-lo+1) * (p-W[2] + 1) = 6
编辑:嗯,似乎有更复杂的解决方案,至少在计算S之后。您可以将其视为问题H:

http://www.informatik.uni-ulm.de/acm/Locals/2003/html/judge.html

这里还有一个相关的SO问题 Maximize the rectangular area under Histogram

编辑:如何使用直方图的想法。

M具有以下结构

1010100101
0001001001
0001000010
0100000000

然后S可以自下而上计算,在这种情况下是

0301041020
3230330310
2120222202
1011111111

现在要找到一条从某条线开始直到最后的矩形,我们使用'直方图问题'。对于第二行,我们有:3230330310,这对应于表格的直方图

X X XX X  
XXX XX X  
XXX XX XX

在此处查找最大的矩形会给出起始问题中最大的矩形。

Complecity:O(n) - 直方图算法。现在,对于每个查询,我们最多检查n行,我们有q个查询,因此:O(n^2 q)