C 求给定二进制数据的最大面积

C 求给定二进制数据的最大面积,c,algorithm,optimization,binary,brute-force,C,Algorithm,Optimization,Binary,Brute Force,我在描述查找二进制数据的最大矩形区域的算法时遇到了一个问题,其中1的出现频率是0的k倍。数据总是n^2位,如下所示: 例如,n=4的数据如下所示: 1010 01 01 10101 k的值可以是1。。j(k=1表示0和1的数量相等)。 对于上述数据示例和k=1,解决方案为: 101020速度太慢了。你能告诉我该如何解决这个问题吗 正如RBerteig所提出的,这个问题也可以这样描述:“在给定的正方形位图中,通过一些任意过程将单元格设置为1或0,找到最大的矩形区域,其中1和0以指定的比例出现,k

我在描述查找二进制数据的最大矩形区域的算法时遇到了一个问题,其中1的出现频率是0的k倍。数据总是n^2位,如下所示:

例如,n=4的数据如下所示:

1010
01
01
10101

k的值可以是1。。j(k=1表示0和1的数量相等)。

对于上述数据示例和k=1,解决方案为:

101020速度太慢了。你能告诉我该如何解决这个问题吗



正如RBerteig所提出的,这个问题也可以这样描述:“在给定的正方形位图中,通过一些任意过程将单元格设置为1或0,找到最大的矩形区域,其中1和0以指定的比例出现,k.”

这仍然是蛮力,但您应该注意的是,对于新的
i*j
矩形,您不必从头开始重新计算所有内容。相反,对于每个可能的矩形大小,您可以在
n*n
网格上一步一步地移动矩形,减少不再在矩形内的位的计数,并增加新进入矩形的位的计数。您可以将这一点与改变矩形大小结合起来,并尝试找到移动和调整矩形大小的最佳模式。

如果正确实施,Bruteforce在n<100的情况下应该可以做得很好:下面的解决方案具有O(n^4)时间和O(n^2)内存复杂性。在现代PC机上,10^8操作应该在1秒以内(特别是考虑到每个操作都非常便宜:几乎没有加法和减法)

一些观察

[LI]有O(n 4)子矩形要考虑,每个都可以是一个解。
  • 若我们能在O(1)(常数时间)中找到每个子矩形中的1和0的数目,我们将在O(n^4)时间内解决这个问题
  • 如果我们知道某个子矩形中1的数量,我们可以找到零的数量(通过区域)
  • 因此,问题归结为以下几点:创建数据结构,允许在固定时间内查找每个子矩形中的1数

    现在,假设我们有子矩形
    [i0..i1]x[j0..j1]
    。即,它占用i0和i1之间的行和j0和j1之间的列。让
    count_one
    作为计算子矩形中1个数的函数

    这是主要观察结果:

    count_ones([i0..i1]x[j0..j1]) = count_ones([0..i1]x[0..j1]) - count_ones([0..i0 - 1]x[0..j1]) - count_ones([0..i1]x[0..j0 - 1]) + count_ones([0..i0 - 1]x[0..j0 - 1])
    
    与实际例子相同的观察结果:

    AAAABBB
    AAAABBB
    CCCCDDD
    CCCCDDD
    CCCCDDD
    CCCCDDD
    
    如果我们需要在D子矩形(3x4)中找到1的数量,我们可以通过计算整个矩形(A+B+C+D)中的1的数量,减去(A+B)矩形中的1的数量,减去(A+C)矩形中的1的数量,再加上(A)矩形中的1的数量来实现<代码>(A+B+C+D)-(A+B)-(A+C)+(A)=D

    因此,我们需要为每个
    i
    j
    求和
    ,它们包含子矩形
    [0..i][0..j]

    您可以在O(n^2)中创建此表,但即使是直接填充它的方式(对于每个
    i
    j
    迭代
    [0..i][0..j]
    区域的所有元素)也将是O(n^4)

    有了这张桌子

    count_ones([i0..i1]x[j0..j1]) = sums[i1][j1] - sums[i0 - 1][j1] - sums[i1][j0 - 1] + sums[i0 - 1][j0 - 1]
    
    因此,时间复杂度O(n^4)达到了。

    只是一些提示

    您可以对这些值施加更好的限制。这一要求导致了条件的改变

    N1*(k+1)==S*k
    ,其中
    N1
    是一个区域中的个数,
    S=dx*dy
    是其表面。 它可以以更好的形式重写:

    N1/k==S/(k+1)

    因为数字
    n
    n+1
    的最大公约数总是1,所以
    N1
    必须是
    k
    的倍数,
    dx*dy
    必须是
    k+1
    的倍数。它大大减少了可能的解空间,越大的
    k
    越好(对于
    dx*dy
    情况,您需要使用
    k+1
    的素数因子)

    现在,因为你只需要拥有这样属性的最大区域的表面,所以明智的做法是从最大的区域开始,移动到较小的区域。通过尝试
    dx*dy
    n^2
    k+1
    满足除数和边界条件,你会很快找到解决方案,比O(n^4)快很多,因为一个特殊的原因:除了特殊构造数组的情况,如果我们假设一个随机输入,在
    (n-dx+1)*(n-dy+1)
    具有表面
    S
    的区域中,
    S
    值中存在
    N1
    的概率将随着
    S
    的减少而不断增加。(较大的
    k
    值将使概率更小,但同时它们将使
    dx
    dy
    对的过滤器更强)


    另外,这个问题:,看起来有些相似,也许你会在他们的解决方案中找到一些想法。

    我不确定我是否理解这个问题。算法应该做什么?算法应该在给定的数据(nxn位)中找到一个矩形扇区,其中“1”的出现频率是“0”的k倍。对于k=1,算法应该找到这样的数据片段,“1”与“0”出现的时间相同。如果数据是1行,我会使用前缀sum,但在这种情况下,我想我不能这样做。这是对问题的正确重述吗?“在给定的正方形位图中,通过一些任意过程将单元格设置为1或0,找到1和0以指定比率出现的最大矩形区域,
    k
    ”对于上面给出的最后一个示例,为什么由完整的三个右侧列组成的矩形不是“解决方案”?值得注意(尽管非常明显)如果比率为k,矩形的面积必须是(k+1)的倍数-这将消除许多矩形。我正在考虑这个解决方案,但当我试图估计步数时,我发现它太复杂了。对于n=200(40000 b