【问题标题】:Split non-square matrix into square sub-matrices将非方阵拆分为方子矩阵
【发布时间】:2020-08-11 03:38:09
【问题描述】:

给定任何非方阵。我正在寻找一种算法将其拆分为N 方形子矩阵。不需要原始矩阵的所有元素都在新的子矩阵中(实际上并不总是可能的),但应该尽可能少。此外,我只需要一种解决方案,而不是所有可能的组合。

例如,如果N=2 并且矩阵是 2x4,则一个除法可能是:

1 1 2 2
1 1 2 2

如果是 2x5 那么:

1 1 2 2 -
1 1 2 2 -

现在最后一列没有分配给任何子矩阵。

固定的是原始数组的大小以及N 子矩阵必须是正方形的事实。所以我必须找到新数组的索引等级。在这个问题here 中,他们提出了类似的问题,但是原始矩阵是正方形的,他们会查找所有组合,在这种情况下,我只需要一个解决方案并且原始矩阵不必是正方形.

有什么想法吗?

【问题讨论】:

    标签: python algorithm matrix


    【解决方案1】:

    我已经实现了自顶向下递归方法。

    给定一个矩阵(x,y,h,w)||(Top Left x-coord, Top Left y-coord, Height, Width),我做了以下事情:-

    假设矩阵 =

    0 0 0 0 0
    0 0 0 0 0
    0 0 0 0 0
    

    我从左上角选择了所有可能大小的正方形:-

    可能性一:

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

    可能性2:

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

    可能性3:

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

    然后我将剩余的空间分成2个矩形并递归。

    例如,可能性 #2 可以通过两种方式打破,x 和 y 表示两个新的工作部分:

    方式一:

    1 1 y y y
    1 1 y y y
    x x y y y
    

    方式二:

    1 1 y y y
    1 1 y y y
    x x x x x
    

    这是一个 Python 实现:

    import sys,copy
    sys.setrecursionlimit(10**4)
    
    
    def display_final_matrix(arr_matrix):
        temp =[['-' for i in range(init_matrix[3])] for j in range(init_matrix[2])]
        ctr=ord('a')
        for matrix in arr_matrix:
            for i in range(matrix[1],matrix[1]+matrix[2]):
                for j in range(matrix[0],matrix[0]+matrix[3]):
                    temp[i][j]=chr(ctr)
            ctr+=1
        for i in temp:
            print(i)
    
    def find_min_leftover(matrix,n):
        x = matrix[0]
        y = matrix[1]
        h = matrix[2]
        w = matrix[3]
        if  n==0:
            return h*w, []
    
        min_left=1<<64
        result_arr=[]
        for i in range(1,min(h,w)+1):
            current_selection = [x,y,i,i]
    
            # Possibility 1
            mtr1 = [x+i,y+0,h,w-i]
            mtr2 = [x+0,y+i,h-i,i]
            for j in range(n):
                left_mtr1 , mtr1_subselection = find_min_leftover(mtr1,j)
                left_mtr2 , mtr2_subselection = find_min_leftover(mtr2,n-1-j)
                if left_mtr1 + left_mtr2 < min_left:
                    min_left = left_mtr1+left_mtr2
                    result_arr =[current_selection]+mtr1_subselection+mtr2_subselection
    
            # Possibility 2
    
            mtr1 = [x+i,y+0,i,w-i]
            mtr2 = [x+0,y+i,h-i,w]
            for j in range(n):
                left_mtr1 , mtr1_subselection = find_min_leftover(mtr1,j)
                left_mtr2 , mtr2_subselection = find_min_leftover(mtr2,n-1-j)
                if left_mtr1 + left_mtr2 < min_left:
                    min_left = left_mtr1+left_mtr2
                    result_arr =[current_selection]+mtr1_subselection+mtr2_subselection
    
        return min_left,result_arr
    
    
    
    
    # Top Left x-coord, Top Left y-coord, Height, Width
    init_matrix = [0,0,6,6]
    
    min_left,final_matrix = find_min_leftover(init_matrix,5)
    
    
    print(min_left)
    print(final_matrix)
    display_final_matrix(final_matrix)
    

    用 5 个正方形填充 6x6 矩阵的输出:

    4
    [[0, 0, 2, 2], [2, 0, 2, 2], [2, 2, 4, 4], [0, 2, 2, 2], [0, 4, 2, 2]]
    ['a', 'a', 'b', 'b', '-', '-']
    ['a', 'a', 'b', 'b', '-', '-']
    ['d', 'd', 'c', 'c', 'c', 'c']
    ['d', 'd', 'c', 'c', 'c', 'c']
    ['e', 'e', 'c', 'c', 'c', 'c']
    ['e', 'e', 'c', 'c', 'c', 'c']
    

    自0&lt;=x,y,h,w&lt;=Max Size以来可以进行记忆。

    4D DP 表运行速度更快,可以一次存储所有结果,但我实施了递归方法,因为它更直观且更易于理解。

    【讨论】:

    • 非常感谢。我没有说(现在我已经编辑了它),但我需要所有子矩阵的大小相同。抱歉,我认为这是隐含的,但显然不是。我的错。
    • 我猜@orlp 的答案是在这种情况下你应该这样做。
    • @Xbel 不,我的答案不适用于所有相同大小的子矩阵。这确实是一个非常关键的要求。我建议提出一个添加了该要求的新问题。
    • @Xbel 您可以计算N 给定大小的正方形是否可以放置在O(1) 的给定矩形中。从那里您可以对答案进行二分搜索,因为直到答案的所有正方形都适合,而没有更大的正方形。 @orlp 这应该可以正常工作吗?
    • 好的。谢谢大家。我想最公平的决定是打开一个新问题并接受这个问题的答案。
    【解决方案2】:

    不难证明,贪心算法总是会尽可能多地覆盖。

    因此,扫描您的矩阵以查找尚未覆盖的第一个元素(例如,从左到右从上到下),并在此处创建一个新的 1 × 1 方形子矩阵。只要它适合原始矩阵,就继续将其向右下角扩展为 2 × 2、3 × 3 等子矩阵。卡住时,从头开始,直到创建 N 个子矩阵。

    【讨论】:

      猜你喜欢
      • 2015-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-22
      • 2020-05-13
      • 1970-01-01
      • 1970-01-01
      • 2018-05-07
      相关资源
      最近更新 更多