2014-10-17 43 views
0

我有0的矩阵和1:如何将矩阵分解为连通分量的总和?

 1 0 0 0 0 
     0 0 1 1 0 
    a = 0 0 1 1 0 
     1 0 0 0 0 
     1 1 0 0 0 

和我想用蟒分解成的连接分量的总和,通过这里的“连接”我的意思是矩阵,其中的每个“1”具有至少在它上面/下面/左边/右边的另一个“1”。否则,“1”必须被隔离:

 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
     0 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 
    a = 0 0 1 1 0 = 0 0 0 0 0 + 0 0 1 1 0 + 0 0 0 0 0 
     1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 
     1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 

这可能是有趣的是,在这个问题上(Largest rectangle of 1's in 2d binary matrix)盖伊阿迪尼建议使用BFS分解分解在连接的组件矩阵。但是我找不到它的python实现,也没有如何使用BFS来解决我的问题。

回答

1

,工程的算法如下:

  • 你保持visited矩阵相同尺寸与真由算法访问(元素或等价地,一组走访元素的坐标)。

  • 您可以通过一个经过矩阵一个的所有元素:

    • 如果一个元素没有被访问和为1,将其标记为已访问,你递归探讨其在同所有邻国办法。递归函数必须返回连接的集合(具有这些集合的矩阵,具有它们的坐标的集合等)。
1

这里来了一个自定义实现。如果需要,我可以修改它以删除重复项。

import itertools 

class Matrix(): 
    def __init__(self, matrix): 
     self.matrix = matrix 

    def computeConnectedComponents(self): 
     rows_id = list(range(len(self.matrix))) 
     cols_id = list(range(len(self.matrix[0]))) 

     #here are the position of every 1 in the grid. (row number, column number) indexes start at 0 
     positions = [couple for couple in self.generate_pairs(rows_id, cols_id) if self.matrix[couple[0]][couple[1]]==1] 

     #here we store all the connected component finded 
     allConnectedComponents = [] 

     #while there is position not affected to any connected component 
     while positions != [] : 
      #the first element is taken as start of the connected component 
      to_explore = [positions.pop(0)] 
      currentConnectedComponent = set() 
      #while there is node connected to a node connected to the component 
      while list(to_explore) != []: 
       currentNode = to_explore.pop() 
       currentConnectedComponent.add(currentNode) 

       to_explore += [coord for coord in self.node_neighbourhood(currentNode) if (self.matrix[coord[0]][coord[1]]==1 and (coord not in to_explore) and (coord not in currentConnectedComponent))] 

       allConnectedComponents.append(currentConnectedComponent) 
       positions = [position for position in positions if position not in currentConnectedComponent] 

     return allConnectedComponents 

    #http://stackoverflow.com/questions/16135833/generate-combinations-of-elements-from-multiple-lists 
    def generate_pairs(self, *args): 
     for i, l in enumerate(args, 1): 
      for x, y in itertools.product(l, itertools.chain(*args[i:])): 
       yield (x, y) 

    def node_neighbourhood(self, coordinates): 
     row, column = coordinates[0], coordinates[1] 
     result = [] 
     if (row - 1) >= 0 : 
      result.append((row-1, column)) 
     if (row + 1) < len(self.matrix): 
      result.append((row+1, column)) 
     if (column - 1) >= 0: 
      result.append((row, column-1)) 
     if (column + 1) < len(self.matrix[0]): 
      result.append((row, column+1)) 
     return result 


if __name__ == "__main__": 
    data = [[1,0,0,0,0], 
      [0,0,1,1,0], 
      [0,0,1,1,0], 
      [1,0,0,0,0], 
      [1,1,0,0,0]] 

    matrix = Matrix(data) 
    for connectedComponent in matrix.computeConnectedComponents(): 
     print(connectedComponent)