Minimum cost to reach from the top-left to the bottom-right corner of a matrix

Given an N * M matrix mat[][] consisting of lower case characters, the task is to find the minimum cost to reach from the cell mat[0][0] to the cell mat[N-1][M-1]. If you are at a cell mat[i][j], you can jump to the cells mat[i+1][j], mat[i][j+1], mat[i-1][j], mat[i][j-1] (without going out of bounds) with a cost of 1. Additionally, you can jump to any cell mat[m][n] such that mat[n][m] = mat[i][j] with a cost of 0.

Examples:

Input: mat[][] = {“abc”, “efg”, “hij”}
Output: 4
One of the shortest path will be:
{0, 0} -> {0, 1} -> {0, 2} -> {1, 2} -> {2, 2}
All the edges have a weight of 1, thus the answer is 4.

Input: mat[][] = {“abc”, “efg”, “hbj”}
Output: 2
{0, 0} -> {0, 1} -> {2, 1} -> {2, 2}
1 + 0 + 1 = 2

Naive approach: One approach for solving this problem will be 0-1 BFS. Visualise the setup as a graph with N * M nodes. All the nodes will be connected to adjacent nodes with an edge of weight 1 and the nodes with the same characters with an edge with weight 0. Now, BFS can be used to find the shortest path from the cell mat[0][0] to the cell mat[N-1][M-1]. The time complexity of this will be O((N * M)2) because the number of edges will be of the order O((N * M)2).



Efficient approach: For each character X, find all the characters it is adjacent to. Now, create a graph with a number of nodes as the number of distinct characters in the string each representing a character.
Each node X will have an edge of weight 1 with all the nodes representing the characters adjacent to the character X in the real graph. Then a BFS can be run from the node representing mat[0][0] to the node representing mat[N-1][M-1] in this new graph. The time complexity of this approach will be O(N * M) for pre-processing the graph and the time complexity for running the BFS can be considered constant.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
  
const int MAX = 26;
  
// Function to return
// the value (x - 97)
int f(int x)
{
    return x - 'a';
}
  
// Fucntion to return the minimum cost
int findMinCost(vector<string> arr)
{
    int n = arr.size();
    int m = arr[0].size();
  
    // Graph
    vector<vector<int> > gr(MAX);
  
    // Adjacency matrix
    bool edge[MAX][MAX];
  
    // Initialising the adjacency matrix
    for (int k = 0; k < MAX; k++)
        for (int l = 0; l < MAX; l++)
            edge[k][l] = 0;
  
    // Creating the adjacency matrix
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++) {
            if (i + 1 < n and !edge[f(arr[i][j])][f(arr[i + 1][j])]) {
                gr[f(arr[i][j])].push_back(f(arr[i + 1][j]));
                edge[f(arr[i][j])][f(arr[i + 1][j])] = 1;
            }
            if (j - 1 >= 0 and !edge[f(arr[i][j])][f(arr[i][j - 1])]) {
                gr[f(arr[i][j])].push_back(f(arr[i][j - 1]));
                edge[f(arr[i][j])][f(arr[i][j - 1])] = 1;
            }
            if (j + 1 < m and !edge[f(arr[i][j])][f(arr[i][j + 1])]) {
                gr[f(arr[i][j])].push_back(f(arr[i][j + 1]));
                edge[f(arr[i][j])][f(arr[i][j + 1])] = 1;
            }
            if (i - 1 >= 0 and !edge[f(arr[i][j])][f(arr[i - 1][j])]) {
                gr[f(arr[i][j])].push_back(f(arr[i - 1][j]));
                edge[f(arr[i][j])][f(arr[i - 1][j])] = 1;
            }
        }
  
    // Queue to perform BFS
    queue<int> q;
    q.push(arr[0][0] - 'a');
  
    // Visited array
    bool v[MAX] = { 0 };
  
    // To store the depth of BFS
    int d = 0;
  
    // BFS
    while (q.size()) {
  
        // Number of elements in
        // the current level
        int cnt = q.size();
  
        // Inner loop
        while (cnt--) {
  
            // Current element
            int curr = q.front();
  
            // Popping queue
            q.pop();
  
            // If the current node has
            // already been visited
            if (v[curr])
                continue;
            v[curr] = 1;
  
            // Checking if the current
            // node is the required node
            if (curr == arr[n - 1][m - 1] - 'a')
                return d;
  
            // Iterating through the current node
            for (auto it : gr[curr])
                q.push(it);
        }
  
        // Updating the depth
        d++;
    }
  
    return -1;
}
  
// Driver code
int main()
{
    vector<string> arr = { "abc",
                           "def",
                           "gbi" };
  
    cout << findMinCost(arr);
  
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java implementation of the approach
import java.util.*;
  
class GFG 
{
  
    static int MAX = 26;
  
    // Function to return
    // the value (x - 97)
    static int f(int x)
    {
        return x - 'a';
    }
  
    // Function to return the minimum cost
    static int findMinCost(String[] arr) 
    {
        int n = arr.length;
        int m = arr[0].length();
  
        // Graph
        Vector<Integer>[] gr = new Vector[MAX];
        for (int i = 0; i < MAX; i++)
            gr[i] = new Vector<Integer>();
  
        // Adjacency matrix
        boolean[][] edge = new boolean[MAX][MAX];
  
        // Initialising the adjacency matrix
        for (int k = 0; k < MAX; k++)
            for (int l = 0; l < MAX; l++)
                edge[k][l] = false;
  
        // Creating the adjacency matrix
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++) 
            {
                if (i + 1 < n && !edge[f(arr[i].charAt(j))][f(arr[i + 1].charAt(j))]) 
                {
                    gr[f(arr[i].charAt(j))].add(f(arr[i + 1].charAt(j)));
                    edge[f(arr[i].charAt(j))][f(arr[i + 1].charAt(j))] = true;
                }
                if (j - 1 >= 0 && !edge[f(arr[i].charAt(j))][f(arr[i].charAt(j - 1))])
                {
                    gr[f(arr[i].charAt(j))].add(f(arr[i].charAt(j - 1)));
                    edge[f(arr[i].charAt(j))][f(arr[i].charAt(j - 1))] = true;
                }
                if (j + 1 < m && !edge[f(arr[i].charAt(j))][f(arr[i].charAt(j + 1))]) 
                {
                    gr[f(arr[i].charAt(j))].add(f(arr[i].charAt(j + 1)));
                    edge[f(arr[i].charAt(j))][f(arr[i].charAt(j + 1))] = true;
                }
                if (i - 1 >= 0 && !edge[f(arr[i].charAt(j))][f(arr[i - 1].charAt(j))]) 
                {
                    gr[f(arr[i].charAt(j))].add(f(arr[i - 1].charAt(j)));
                    edge[f(arr[i].charAt(j))][f(arr[i - 1].charAt(j))] = true;
                }
            }
  
        // Queue to perform BFS
        Queue<Integer> q = new LinkedList<Integer>();
        q.add(arr[0].charAt(0) - 'a');
  
        // Visited array
        boolean[] v = new boolean[MAX];
  
        // To store the depth of BFS
        int d = 0;
  
        // BFS
        while (q.size() > 0)
        {
  
            // Number of elements in
            // the current level
            int cnt = q.size();
  
            // Inner loop
            while (cnt-- > 0)
            {
  
                // Current element
                int curr = q.peek();
  
                // Popping queue
                q.remove();
  
                // If the current node has
                // already been visited
                if (v[curr])
                    continue;
                v[curr] = true;
  
                // Checking if the current
                // node is the required node
                if (curr == arr[n - 1].charAt(m - 1) - 'a')
                    return d;
  
                // Iterating through the current node
                for (Integer it : gr[curr])
                    q.add(it);
            }
  
            // Updating the depth
            d++;
        }
  
        return -1;
    }
  
    // Driver code
    public static void main(String[] args) 
    {
        String[] arr = { "abc", "def", "gbi" };
  
        System.out.print(findMinCost(arr));
  
    }
}
  
// This code is contributed by 29AjayKumar

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 implementation of the approach
MAX = 26
  
# Function to return
# the value (x - 97)
def f(x):
    return ord(x) - ord('a')
  
# Fucntion to return the minimum cost
def findMinCost( arr):
    global MAX
    n = len(arr)
    m = len(arr[0])
  
    # Graph
    gr = []
      
    for x in range(MAX):
        gr.append([])
  
    # Adjacency matrix
    edge = []
  
    # Initialising the adjacency matrix
    for k in range(MAX):
        edge.append([])
        for l in range(MAX):
            edge[k].append(0)
  
    # Creating the adjacency matrix
    for i in range(n):
        for j in range(m): 
            if (i + 1 < n and edge[f(arr[i][j])][f(arr[i + 1][j])] == 0): 
                gr[f(arr[i][j])].append(f(arr[i + 1][j]))
                edge[f(arr[i][j])][f(arr[i + 1][j])] = 1
              
            if (j - 1 >= 0 and edge[f(arr[i][j])][f(arr[i][j - 1])] == 0): 
                gr[f(arr[i][j])].append(f(arr[i][j - 1]))
                edge[f(arr[i][j])][f(arr[i][j - 1])] = 1
              
            if (j + 1 < m and edge[f(arr[i][j])][f(arr[i][j + 1])] == 0): 
                gr[f(arr[i][j])].append(f(arr[i][j + 1]))
                edge[f(arr[i][j])][f(arr[i][j + 1])] = 1
              
            if (i - 1 >= 0 and edge[f(arr[i][j])][f(arr[i - 1][j])] == 0): 
                gr[f(arr[i][j])].append(f(arr[i - 1][j]))
                edge[f(arr[i][j])][f(arr[i - 1][j])] = 1
              
    # Queue to perform BFS
    q = []
    q.append(ord(arr[0][0]) - ord('a'))
  
    # Visited array
    v = []
    for i in range(MAX):
        v.append(0)
  
    # To store the depth of BFS
    d = 0
  
    # BFS
    while (len(q) > 0): 
  
        # Number of elements in
        # the current level
        cnt = len(q)
  
        # Inner loop
        while (cnt > 0): 
            cnt = cnt - 1
              
            # Current element
            curr = q[0]
  
            # Popping queue
            q.pop(0)
  
            # If the current node has
            # already been visited
            if (v[curr] != 0):
                continue
            v[curr] = 1
              
            # Checking if the current
            # node is the required node
            if (curr == (ord(arr[n - 1][m - 1]) - ord('a'))):
                return d
  
            # Iterating through the current node
            for it in gr[curr]:
                q.append(it)
          
        # Updating the depth
        d = d + 1
  
    return -1
  
# Driver code
arr =[ "abc","def","gbi" ]
print( findMinCost(arr))
  
# This code is contributed by Arnab Kundu

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# implementation of the approach
using System;
using System.Collections.Generic;
  
class GFG 
{
  
    static int MAX = 26;
  
    // Function to return
    // the value (x - 97)
    static int f(int x)
    {
        return x - 'a';
    }
  
    // Function to return the minimum cost
    static int findMinCost(String[] arr) 
    {
        int n = arr.Length;
        int m = arr[0].Length;
  
        // Graph
        List<int>[] gr = new List<int>[MAX];
        for (int i = 0; i < MAX; i++)
            gr[i] = new List<int>();
  
        // Adjacency matrix
        bool[,] edge = new bool[MAX, MAX];
  
        // Initialising the adjacency matrix
        for (int k = 0; k < MAX; k++)
            for (int l = 0; l < MAX; l++)
                edge[k,l] = false;
  
        // Creating the adjacency matrix
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++) 
            {
                if (i + 1 < n && !edge[f(arr[i][j]),f(arr[i + 1][j])]) 
                {
                    gr[f(arr[i][j])].Add(f(arr[i + 1][j]));
                    edge[f(arr[i][j]), f(arr[i + 1][j])] = true;
                }
                if (j - 1 >= 0 && !edge[f(arr[i][j]),f(arr[i][j - 1])])
                {
                    gr[f(arr[i][j])].Add(f(arr[i][j - 1]));
                    edge[f(arr[i][j]), f(arr[i][j - 1])] = true;
                }
                if (j + 1 < m && !edge[f(arr[i][j]),f(arr[i][j + 1])]) 
                {
                    gr[f(arr[i][j])].Add(f(arr[i][j + 1]));
                    edge[f(arr[i][j]), f(arr[i][j + 1])] = true;
                }
                if (i - 1 >= 0 && !edge[f(arr[i][j]),f(arr[i - 1][j])]) 
                {
                    gr[f(arr[i][j])].Add(f(arr[i - 1][j]));
                    edge[f(arr[i][j]), f(arr[i - 1][j])] = true;
                }
            }
  
        // Queue to perform BFS
        Queue<int> q = new Queue<int>();
        q.Enqueue(arr[0][0] - 'a');
  
        // Visited array
        bool[] v = new bool[MAX];
  
        // To store the depth of BFS
        int d = 0;
  
        // BFS
        while (q.Count > 0)
        {
  
            // Number of elements in
            // the current level
            int cnt = q.Count;
  
            // Inner loop
            while (cnt-- > 0)
            {
  
                // Current element
                int curr = q.Peek();
  
                // Popping queue
                q.Dequeue();
  
                // If the current node has
                // already been visited
                if (v[curr])
                    continue;
                v[curr] = true;
  
                // Checking if the current
                // node is the required node
                if (curr == arr[n - 1][m - 1] - 'a')
                    return d;
  
                // Iterating through the current node
                foreach (int it in gr[curr])
                    q.Enqueue(it);
            }
  
            // Updating the depth
            d++;
        }
  
        return -1;
    }
  
    // Driver code
    public static void Main(String[] args) 
    {
        String[] arr = { "abc", "def", "gbi" };
  
        Console.Write(findMinCost(arr));
    }
}
  
// This code is contributed by 29AjayKumar

chevron_right


Output:

2

Don’t stop now and take your learning to the next level. Learn all the important concepts of Data Structures and Algorithms with the help of the most trusted course: DSA Self Paced. Become industry ready at a student-friendly price.




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Improved By : 29AjayKumar, andrew1234