Open In App

Shortest Path to Get Food in Matrix

Given a matrix grid[][], where '*' represents your location, '#' represents food cells, 'O' represents free space, 'X' represents obstacles. The task is to find the shortest path from your location to any food cell in a given matrix grid, Return the length of the shortest path to reach any food cell, or -1 if no path exists.

Example:

Input: grid = [["X","X","X","X","X","X"],["X","*","O","O","O","X"],["X","O","O","#","O","X"],["X","X","X","X","X","X"]]
Output: 3
Explanation: only 3 steps needed o reach the food.

Input: grid = [["X","X","X","X","X"],["X","*","X","O","X"],["X","O","X","#","X"],["X","X","X","X","X"]]
Output: -1
Explanation: Not possible to reach the food.

Approach:

The idea is to use multi-source Breadth-First Search (BFS) algorithm. Starts the BFS from the given location and explores the neighbor nodes at the present depth prior to moving on to nodes at the next depth level.

This property of BFS is useful in this problem because it guarantees that we explore all cells at a given distance before moving on to the cells at the next distance. Therefore, the first time we reach a food cell, we can be sure that we have found the shortest path.

Steps-by-step approach:

Below are the implementation of the above approach:

#include <bits/stdc++.h>
using namespace std;

// Function to find the shortest path from your location to
// any food cell
int findShortestPathToFood(vector<vector<char> >& grid)
{
    // Initialize a queue to keep track of cells to visit
    queue<vector<int> > Q; // <value, distance, x, y>

    /*
        we mapped grid value to integer:
        '*': 1
        '#': 2
        'O': 3

    */

    // Define the four possible directions to move in the
    // grid
    vector<vector<int> > directions
        = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } };

    // Get the size of the grid
    int numRows = grid.size(), numCols = grid[0].size();

    // Find your location in the grid and add it to the
    // queue
    for (int row = 0; row < numRows; row++) {
        for (int col = 0; col < numCols; col++) {
            if (grid[row][col] == '*') {
                Q.push({ 1, 0, row, col });
            }
        }
    }

    // Initialize the result to -1 (no path found)
    int shortestPathLength = -1;

    // Create a visited matrix to keep track of visited
    // cells
    vector<vector<int> > visited(numRows,
                                 vector<int>(numCols));

    // Start BFS
    while (!Q.empty()) {
        auto currentCell = Q.front();
        Q.pop();

        // If we have reached a food cell, update the
        // shortest path length and break
        if (currentCell[0] == 2) {
            shortestPathLength = currentCell[1];
            break;
        }

        // Visit all adjacent cells
        for (int i = 0; i < 4; i++) {
            int newRow = directions[i][0] + currentCell[2];
            int newCol = directions[i][1] + currentCell[3];

            // If the new cell is within the grid, not an
            // obstacle, and not visited
            if (newRow >= 0 && newRow < numRows
                && newCol >= 0 && newCol < numCols
                && (grid[newRow][newCol] == 'O'
                    || grid[newRow][newCol] == '#')
                && visited[newRow][newCol] == 0) {
                // Mark the new cell as visited
                visited[newRow][newCol] = 1;

                // If the new cell is a food cell, add it to
                // the queue with a priority of 2
                if (grid[newRow][newCol] == '#') {
                    Q.push({ 2, currentCell[1] + 1, newRow,
                             newCol });
                }
                // If the new cell is a free space, add it
                // to the queue with a priority of 3
                else {
                    Q.push({ 3, currentCell[1] + 1, newRow,
                             newCol });
                }
            }
        }
    }

    // Return the length of the shortest path to reach any
    // food cell, or -1 if no path exists
    return shortestPathLength;
}

int main()
{

    vector<vector<char> > grid
        = { { 'X', 'X', 'X', 'X', 'X', 'X' },
            { 'X', '*', 'O', 'O', 'O', 'X' },
            { 'X', 'O', 'O', '#', 'O', 'X' },
            { 'X', 'X', 'X', 'X', 'X', 'X' } };

    cout << findShortestPathToFood(grid);

    return 0;
}
import java.util.LinkedList;
import java.util.Queue;

public class GFG {

    // Function to find the shortest path from your location to
    // any food cell
    public static int findShortestPathToFood(char[][] grid) {
        // Initialize a queue to keep track of cells to visit
        Queue<int[]> queue = new LinkedList<>(); // <value, distance, x, y>

        /*
            we mapped grid value to integer:
            '*': 1
            '#': 2
            'O': 3

        */

        // Define the four possible directions to move in the
        // grid
        int[][] directions = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

        // Get the size of the grid
        int numRows = grid.length;
        int numCols = grid[0].length;

        // Find your location in the grid and add it to the
        // queue
        for (int row = 0; row < numRows; row++) {
            for (int col = 0; col < numCols; col++) {
                if (grid[row][col] == '*') {
                    queue.add(new int[]{1, 0, row, col});
                }
            }
        }

        // Initialize the result to -1 (no path found)
        int shortestPathLength = -1;

        // Create a visited matrix to keep track of visited
        // cells
        boolean[][] visited = new boolean[numRows][numCols];

        // Start BFS
        while (!queue.isEmpty()) {
            int[] currentCell = queue.poll();

            // If we have reached a food cell, update the
            // shortest path length and break
            if (currentCell[0] == 2) {
                shortestPathLength = currentCell[1];
                break;
            }

            // Visit all adjacent cells
            for (int[] direction : directions) {
                int newRow = direction[0] + currentCell[2];
                int newCol = direction[1] + currentCell[3];

                // If the new cell is within the grid, not an
                // obstacle, and not visited
                if (newRow >= 0 && newRow < numRows
                        && newCol >= 0 && newCol < numCols
                        && (grid[newRow][newCol] == 'O'
                        || grid[newRow][newCol] == '#')
                        && !visited[newRow][newCol]) {
                    // Mark the new cell as visited
                    visited[newRow][newCol] = true;

                    // If the new cell is a food cell, add it to
                    // the queue with a priority of 2
                    if (grid[newRow][newCol] == '#') {
                        queue.add(new int[]{2, currentCell[1] + 1, newRow, newCol});
                    }
                    // If the new cell is a free space, add it
                    // to the queue with a priority of 3
                    else {
                        queue.add(new int[]{3, currentCell[1] + 1, newRow, newCol});
                    }
                }
            }
        }

        // Return the length of the shortest path to reach any
        // food cell, or -1 if no path exists
        return shortestPathLength;
    }

    public static void main(String[] args) {

        char[][] grid = {
                {'X', 'X', 'X', 'X', 'X', 'X'},
                {'X', '*', 'O', 'O', 'O', 'X'},
                {'X', 'O', 'O', '#', 'O', 'X'},
                {'X', 'X', 'X', 'X', 'X', 'X'}
        };

        System.out.println(findShortestPathToFood(grid));
    }
}
from collections import deque

# Function to find the shortest path from your location to any food cell
def findShortestPathToFood(grid):
    # Define the four possible directions to move in the grid
    directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]

    # Get the size of the grid
    numRows, numCols = len(grid), len(grid[0])

    # Initialize a queue to keep track of cells to visit
    Q = deque()  # (value, distance, x, y)

    # Find your location in the grid and add it to the queue
    for row in range(numRows):
        for col in range(numCols):
            if grid[row][col] == '*':
                Q.append((1, 0, row, col))

    # Initialize the result to -1 (no path found)
    shortestPathLength = -1

    # Create a visited matrix to keep track of visited cells
    visited = [[0] * numCols for _ in range(numRows)]

    # Start BFS
    while Q:
        currentCell = Q.popleft()

        # If we have reached a food cell, update the shortest path length and break
        if currentCell[0] == 2:
            shortestPathLength = currentCell[1]
            break

        # Visit all adjacent cells
        for direction in directions:
            newRow, newCol = direction[0] + currentCell[2], direction[1] + currentCell[3]

            # If the new cell is within the grid, not an obstacle, and not visited
            if 0 <= newRow < numRows and 0 <= newCol < numCols and (grid[newRow][newCol] == 'O' or grid[newRow][newCol] == '#') and not visited[newRow][newCol]:
                # Mark the new cell as visited
                visited[newRow][newCol] = 1

                # If the new cell is a food cell, add it to the queue with a priority of 2
                if grid[newRow][newCol] == '#':
                    Q.append((2, currentCell[1] + 1, newRow, newCol))
                # If the new cell is a free space, add it to the queue with a priority of 3
                else:
                    Q.append((3, currentCell[1] + 1, newRow, newCol))

    # Return the length of the shortest path to reach any food cell, or -1 if no path exists
    return shortestPathLength

# Driver code
if __name__ == "__main__":
    grid = [
        ['X', 'X', 'X', 'X', 'X', 'X'],
        ['X', '*', 'O', 'O', 'O', 'X'],
        ['X', 'O', 'O', '#', 'O', 'X'],
        ['X', 'X', 'X', 'X', 'X', 'X']
    ]

    print(findShortestPathToFood(grid))
// Function to find the shortest path from your location to any food cell
function findShortestPathToFood(grid) {
    // Initialize a queue to keep track of cells to visit
    const queue = []; // [value, distance, x, y]

    /*
        We mapped grid value to integer:
        '*': 1
        '#': 2
        'O': 3
    */

    // Define the four possible directions to move in the grid
    const directions = [[1, 0], [-1, 0], [0, 1], [0, -1]];

    // Get the size of the grid
    const numRows = grid.length;
    const numCols = grid[0].length;

    // Find your location in the grid and add it to the queue
    for (let row = 0; row < numRows; row++) {
        for (let col = 0; col < numCols; col++) {
            if (grid[row][col] === '*') {
                queue.push([1, 0, row, col]);
            }
        }
    }

    // Initialize the result to -1 (no path found)
    let shortestPathLength = -1;

    // Create a visited matrix to keep track of visited cells
    const visited = new Array(numRows).fill(null).map(() => new Array(numCols).fill(false));

    // Start BFS
    while (queue.length) {
        const currentCell = queue.shift();

        // If we have reached a food cell, update the shortest path length and break
        if (currentCell[0] === 2) {
            shortestPathLength = currentCell[1];
            break;
        }

        // Visit all adjacent cells
        for (const direction of directions) {
            const newRow = direction[0] + currentCell[2];
            const newCol = direction[1] + currentCell[3];

            // If the new cell is within the grid, not an obstacle, and not visited
            if (newRow >= 0 && newRow < numRows
                && newCol >= 0 && newCol < numCols
                && (grid[newRow][newCol] === 'O' || grid[newRow][newCol] === '#')
                && !visited[newRow][newCol]) {
                // Mark the new cell as visited
                visited[newRow][newCol] = true;

                // If the new cell is a food cell, add it to the queue with a priority of 2
                if (grid[newRow][newCol] === '#') {
                    queue.push([2, currentCell[1] + 1, newRow, newCol]);
                }
                // If the new cell is a free space, add it to the queue with a priority of 3
                else {
                    queue.push([3, currentCell[1] + 1, newRow, newCol]);
                }
            }
        }
    }

    // Return the length of the shortest path to reach any food cell, or -1 if no path exists
    return shortestPathLength;
}

// Driver code
const grid = [
    ['X', 'X', 'X', 'X', 'X', 'X'],
    ['X', '*', 'O', 'O', 'O', 'X'],
    ['X', 'O', 'O', '#', 'O', 'X'],
    ['X', 'X', 'X', 'X', 'X', 'X']
];

console.log(findShortestPathToFood(grid));

Output
3

Time complexity: O(N*M), where N and M are the number of rows and columns in the given matrix
Auxiliary Space: O(N*M)


Article Tags :