Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Find the minimum number of moves needed to move from one cell of matrix to another in Python
Finding the minimum number of moves to navigate from one cell to another in a matrix is a classic pathfinding problem. We can solve this using Breadth-First Search (BFS) algorithm by treating the matrix as a graph where each cell is a node.
Problem Understanding
In this problem, we have an N × N matrix with specific cell values ?
Cell with value 1 indicates Source
Cell with value 2 indicates Destination
Cell with value 3 indicates Blank cell (walkable)
Cell with value 0 indicates Wall (blocked)
We can move in four directions: up, down, left, and right. Each move counts as 1 step.
Example Matrix
| 3 | 3 | 1 | 0 |
| 3 | 0 | 3 | 3 |
| 3 | 3 | 0 | 3 |
| 0 | 3 | 2 | 3 |
The shortest path from source (1) to destination (2) takes 5 moves.
Solution Using BFS
We'll create a graph where each valid cell is a node, then use BFS to find the shortest path ?
from collections import deque
class Graph:
def __init__(self, nodes):
self.nodes = nodes
self.adj = [[] for i in range(nodes)]
def insert_edge(self, src, dest):
self.adj[src].append(dest)
self.adj[dest].append(src)
def BFS(self, src, dest):
if src == dest:
return 0
level = [-1] * self.nodes
queue = deque([src])
level[src] = 0
while queue:
current = queue.popleft()
for neighbor in self.adj[current]:
if level[neighbor] == -1: # Not visited
level[neighbor] = level[current] + 1
queue.append(neighbor)
if neighbor == dest:
return level[neighbor]
return -1 # No path found
def is_valid(i, j, matrix, order):
return (0 <= i < order and 0 <= j < order and matrix[i][j] != 0)
def get_min_moves(matrix):
order = len(matrix)
src, dest = None, None
nodes = order * order + 2
graph = Graph(nodes)
# Map each cell to a node number
k = 1
for i in range(order):
for j in range(order):
if matrix[i][j] != 0:
# Connect to adjacent valid cells
if is_valid(i, j + 1, matrix, order): # Right
graph.insert_edge(k, k + 1)
if is_valid(i, j - 1, matrix, order): # Left
graph.insert_edge(k, k - 1)
if is_valid(i + 1, j, matrix, order): # Down
graph.insert_edge(k, k + order)
if is_valid(i - 1, j, matrix, order): # Up
graph.insert_edge(k, k - order)
# Mark source and destination
if matrix[i][j] == 1:
src = k
elif matrix[i][j] == 2:
dest = k
k += 1
return graph.BFS(src, dest)
# Test the solution
matrix = [
[3, 3, 1, 0],
[3, 0, 3, 3],
[3, 3, 0, 3],
[0, 3, 2, 3]
]
result = get_min_moves(matrix)
print(f"Minimum moves required: {result}")
Minimum moves required: 5
How It Works
The algorithm works in these steps ?
Graph Construction: Each valid cell (not a wall) becomes a node in the graph
Edge Creation: Connect adjacent walkable cells with edges
BFS Traversal: Use BFS to find the shortest path from source to destination
Level Tracking: Track the distance (number of moves) from the source
Alternative Direct BFS Approach
Here's a simpler approach that works directly on the matrix ?
from collections import deque
def find_min_moves_direct(matrix):
if not matrix or not matrix[0]:
return -1
rows, cols = len(matrix), len(matrix[0])
src_pos = dest_pos = None
# Find source and destination positions
for i in range(rows):
for j in range(cols):
if matrix[i][j] == 1:
src_pos = (i, j)
elif matrix[i][j] == 2:
dest_pos = (i, j)
if not src_pos or not dest_pos:
return -1
# BFS
queue = deque([(src_pos[0], src_pos[1], 0)]) # (row, col, moves)
visited = set([src_pos])
directions = [(0, 1), (0, -1), (1, 0), (-1, 0)] # right, left, down, up
while queue:
row, col, moves = queue.popleft()
if (row, col) == dest_pos:
return moves
for dr, dc in directions:
new_row, new_col = row + dr, col + dc
if (0 <= new_row < rows and 0 <= new_col < cols and
matrix[new_row][new_col] != 0 and
(new_row, new_col) not in visited):
visited.add((new_row, new_col))
queue.append((new_row, new_col, moves + 1))
return -1 # No path found
# Test with the same matrix
matrix = [
[3, 3, 1, 0],
[3, 0, 3, 3],
[3, 3, 0, 3],
[0, 3, 2, 3]
]
result = find_min_moves_direct(matrix)
print(f"Minimum moves required: {result}")
Minimum moves required: 5
Comparison
| Approach | Time Complexity | Space Complexity | Implementation |
|---|---|---|---|
| Graph-based BFS | O(N²) | O(N²) | More complex |
| Direct BFS on Matrix | O(N²) | O(N²) | Simpler |
Conclusion
Both approaches use BFS to find the shortest path, but the direct matrix approach is simpler and more intuitive. The key insight is treating the matrix as a graph where each valid cell connects to its adjacent walkable neighbors.
