There is a strange printer with the following two special requirements:
On each turn, the printer will print a solid rectangular pattern of a single color on the grid. This will cover up the existing colors in the rectangle.
Once the printer has used a color for the above operation, the same color cannot be used again.
You are given a m x n matrix targetGrid, where targetGrid[row][col] is the color in the position (row, col) of the grid.
Return trueif it is possible to print the matrixtargetGrid,otherwise, returnfalse.
Input: targetGrid = [[1,2,1],[2,1,2],[1,2,1]]
Output: false
Explanation: It is impossible to form targetGrid because it is not allowed to print the same color in different turns.
defcontains(self, row: int, col: int) -> bool: return self.top <= row <= self.bottom and self.left <= col <= self.right
defhas_circle(graph: dict[int, set[int]]) -> bool: nodes = {u: Falsefor u in graph} # False: not processed; True: processing; <Removed>: finished. while nodes: stack = [next(iter(nodes))] while stack: u = stack.pop() if u notin nodes: # `u` is already finished. continue elif nodes[u]: # `u` is under processing, then finish it. nodes.pop(u) continue
nodes[u] = True# `u` is not processed, mark it processing. stack.append(u) for v in graph[u]: if v in nodes: if nodes[v]: # If `v` is under processing, there is a circle. returnTrue stack.append(v) # `v` is not processed (and not finished).
returnFalse
defhas_circle2(graph: dict[int, set[int]]) -> bool: in_degrees = defaultdict(int, {u: 0for u in graph}) # u: u's in-degree. for u in graph: for v in graph[u]: in_degrees[v] += 1
while in_degrees: zero = next((u for u, d in in_degrees.items() if d == 0), None) if zero isNone: returnTrue
in_degrees.pop(zero) for v in graph[zero]: if v in in_degrees: in_degrees[v] -= 1
returnFalse
classSolution: defisPrintable(self, targetGrid: list[list[int]]) -> bool: m = len(targetGrid) n = len(targetGrid[0])
# Get surrounding boxes for each color. boxes: dict[int, Rect] = {} # {color: surrounding rectangle} for i inrange(m): for j inrange(n): c = targetGrid[i][j] if c notin boxes: boxes[c] = Rect(i, j) else: boxes[c].extend(i, j)
# Build a dependency graph. graph: dict[int, set[int]] = defaultdict(set) # {color: other colors should print later} # graph = {c: set() for c in boxes} for i inrange(m): for j inrange(n): c = targetGrid[i][j] for c2, box in boxes.items(): if c2 != c and box.contains(i, j): graph[c2].add(c)
defcontains(self, row: int, col: int) -> bool: return self.top <= row <= self.bottom and self.left <= col <= self.right
classSolution: defisPrintable(self, targetGrid: list[list[int]]) -> bool: m = len(targetGrid) n = len(targetGrid[0]) boxes: dict[int, Rect] = {} # {color: surrounding rectangle} counts: dict[int, int] = defaultdict(int) # {color: number of cells can be printed to this color} for i inrange(m): for j inrange(n): color = targetGrid[i][j] counts[color] += 1 if color notin boxes: boxes[color] = Rect(i, j) else: boxes[color].extend(i, j)
while counts: color = next((c for c, cnt in counts.items() if cnt == boxes[c].area), None) if color isNone: returnFalse
box = boxes[color] for i inrange(box.top, box.bottom + 1): for j inrange(box.left, box.right + 1): if targetGrid[i][j] != color: continue for c2 in counts: box2 = boxes[c2] if c2 != color and box2.contains(i, j): counts[c2] += 1