Program to check person can reach top-left or bottomright cell avoiding fire or not in Python


Suppose we have a 2D matrix with few different values like below −

  • 0 for empty cell

  • 1 for a person

  • 2 for fire

  • 3 for a wall

Now assume there is only one person and in each turn the fire expands in all four directions (up, down, left and right) but fire cannot expand through walls. We have to check whether the person can move to either the top-left corner or the bottom-right corner or the matrix. We have to keep in mind that in each turn, the person moves first, then the fire expands. If the person makes it to any of the target cells as the same time as the fire, then he is safe. So if person go to the cell and then the fire expands in the same turn to the same cell, the person still survives.

So, if the input is like

000
001
002

then the output will be True, as the person can go to the top left corner.

To solve this, we will follow these steps −

  • R := row count of A, C := column count of A

  • Define a function bfs() . This will take queue

  • dist := a map that contains key as node of queue and all values are 0

  • while queue is not empty, do

    • node := left item of queue, then delete left item

    • for each neighbor nei of node, do

      • if nei is not in dist, then

        • dist[nei] := dist[node] + 1

        • insert nei at the end of queue

  • return dist

  • From the main method do the following −

  • fire_que := a double ended queue

  • person_que := a double ended queue

  • for each row index r and row A, do

    • for each column index c and value v in row, do

      • if v is same as 1, then

        • insert pair (r, c) at the end of person_que

      • otherwise when v is same as 2, then

        • insert pair (r, c) at the end of fire_que

        • dist_fire := bfs(fire_que)

  • dist_person := bfs(person_que)

  • for each place in (0, 0), (R − 1, C − 1), do

    • if (dist_fire[place] if not exists then INF) >= (dist_person[place] if not exists then, 2 * INF), then

      • return True

  • return False

Let us see the following implementation to get better understanding −

Example

 Live Demo

from collections import deque
class Solution:
   def solve(self, A):
      INF = int(1e9)
      R, C = len(A), len(A[0])
      def get_nei(r, c):
         for nr, nc in [[r − 1, c], [r, c − 1], [r + 1, c], [r, c + 1]]:
            if 0 <= nr < R and 0 <= nc < C and A[nr][nc] != 3:
               yield nr, nc
         def bfs(queue):
            dist = {node: 0 for node in queue}
            while queue:
               node = queue.popleft()
               for nei in get_nei(*node):
                  if nei not in dist:
                     dist[nei] = dist[node] + 1
                     queue.append(nei)
            return dist
         fire_que = deque()
         person_que = deque()
         for r, row in enumerate(A):
            for c, v in enumerate(row):
               if v == 1:
                  person_que.append((r, c))
               elif v == 2:
                  fire_que.append((r, c))
         dist_fire = bfs(fire_que)
         dist_person = bfs(person_que)
         for place in ((0, 0), (R− 1, C− 1)):
            if dist_fire.get(place, INF) >= dist_person.get(place, 2 * INF):
               return True
         return False
ob = Solution()
matrix = [
   [0, 0, 0],
   [0, 0, 1],
   [0, 0, 2]
]
print(ob.solve(matrix))

Input

[ [0, 0, 0], [0, 0, 1], [0, 0, 2] ]

Output

True

Updated on: 26-Dec-2020

60 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements