2014-10-17 45 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)