【问题标题】:Count the number of positions in a matrix which form a rectangle计算矩阵中形成矩形的位置数
【发布时间】:2023-02-24 03:14:40
【问题描述】:

我有一个仅包含 0 和 1 的方阵。例如,

1  0  1  1  1
1  1  0  0  1
1  0  1  1  0
0  1  1  1  1
1  0  1  1  1

我想计算顶点为 1 且边与矩阵的行和列平行的矩形的数量。矩形的边缘允许有 0。这是一个这样的矩形的例子(它的顶点在方括号中)

[1]  0  1  1  [1]
 1   1  0  0   1
 1   0  1  1   0
 0   1  1  1   1
[1]  0  1  1  [1]

我已经查看了link1link2 但仍然没有任何线索..

【问题讨论】:

  • 你计算包含在更大矩形内的矩形吗?重叠的矩形怎么样?
  • @ravenspoint 是的,所有这些都很重要。如果一个矩形包含在一个更大的矩形中,则两者都被计算在内。如果两个矩形重叠,则两者都被计算在内。
  • 由于复杂性至少与输出的长度一样高,所以您不妨暴力破解它。 for left in range(width): for top in range(height): if matrix[top, left] == 1: for right in range(left+1, width): if matrix[top, right] == 1: for bottom in range(top+1, height): if matrix[bottom, left] == matrix[bottom, right] == 1: yield (left, top, right, bottom)

标签: algorithm graph combinatorics rectangles discrete-mathematics


【解决方案1】:
- LOOP C over cells in the matrix
   - LOOP S over possible rectangle sizes, starting from this cell
       - Set found TRUE
       - LOOP R over cells forming rectangle of size S with top left at C
            - IF R contain 0
                  - SET found false
                  - BREAK from LOOP R
       - IF found
            Add to count

例子:

matrix 5 by 5
start cell 1,1  ( zero-based )
maximum rectangle is 4 by 4
check cells at  1,4    4,1    and 4,4
if all contain 1s you have found a 4 by 4 rectangle

【讨论】:

    【解决方案2】:

    由于复杂性至少与输出的长度一样高,所以您不妨暴力破解它。

    def gen_rectangles(matrix):
      height, width = matrix.shape
      for left in range(width):
        for top in range(height):
          if matrix[top, left] == 1:
            for right in range(left+1, width):
              if matrix[top, right] == 1:
                for bottom in range(top+1, height):
                  if matrix[bottom, left] == matrix[bottom, right] == 1:
                    yield (top, left, bottom, right)
    
    import numpy as np
    matrix = np.array([[int(x) for x in row.split()] for row in
    '''1  0  1  1  1
    1  1  0  0  1
    1  0  1  1  0
    0  1  1  1  1
    1  0  1  1  1'''.split('
    ')])
    
    print(list(gen_rectangles(matrix)))
    # [(0, 0, 2, 2), (0, 0, 4, 2), (0, 0, 2, 3), (0, 0, 4, 3), (0, 0, 1, 4), (0, 0, 4, 4), (1, 0, 4, 4), (2, 0, 4, 2), (2, 0, 4, 3), (1, 1, 3, 4), (0, 2, 2, 3), (0, 2, 3, 3), (0, 2, 4, 3), (0, 2, 3, 4), (0, 2, 4, 4), (2, 2, 3, 3), (2, 2, 4, 3), (3, 2, 4, 3), (3, 2, 4, 4), (0, 3, 3, 4), (0, 3, 4, 4), (3, 3, 4, 4)]
    

    【讨论】:

      【解决方案3】:

      在最坏的情况下,矩阵没有零,因此它可以有 O(?2个) 左上角与尽可能多的右下角相结合,使得 O(?4个) 矩形。

      所以如果你必须输出每个矩形,时间复杂度将是 O(?4个).但是因为你只需要数数矩形而不是自己生成矩形,你可以节省一些时间,并且时间复杂度为 O(?3个).

      这个想法是选择每一对可能的行,然后计算在两个选定行中有多少列为 1。应考虑 2x2 的每个组合。这是一个三角数:如果 1-1 对的数量是 ?,那么可以用它们组成的矩形数是 ?(?-1)/2。

      在 JavaScript 中的实现:

      function countRectangles(rect) {
          let count = 0;
          for (let y2 = 1; y2 < rect.length; y2++) {
              for (let y1 = 0; y1 < y2; y1++) {
                  let pairs = 0;
                  for (let x = 0; x < rect[0].length; x++) {
                      if (rect[y1][x] + rect[y2][x] == 2) {
                          pairs++;
                      }
                  }
                  // Count in how many ways 2 pairs of corners can be combined
                  count += pairs * (pairs - 1) / 2;
              }
          }
          return count;
      }
      
      const rect = [
          [1,  0,  1,  1,  1],
          [1,  1,  0,  0,  1],
          [1,  0,  1,  1,  0],
          [0,  1,  1,  1,  1],
          [1,  0,  1,  1,  1],
      ]
      
      console.log(countRectangles(rect)); // 22

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-31
        • 2011-08-12
        相关资源
        最近更新 更多