Open In App

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

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

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:
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:
{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++




// 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';
}
 
// Function 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;
}


Java




// 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


Python3




# Python3 implementation of the approach
MAX = 26
 
# Function to return
# the value (x - 97)
def f(x):
    return ord(x) - ord('a')
 
# Function 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


C#




// 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


Javascript




// Javascript implementation of the approach
 
const MAX = 26;
 
// Function to return the value (x - 97)
function f(x) {
  return x.charCodeAt(0) - 'a'.charCodeAt(0);
}
 
// Function to return the minimum cost
function findMinCost(arr) {
  let n = arr.length;
  let m = arr[0].length;
 
  // Graph
  let gr = [];
 
  for (let x = 0; x < MAX; x++) {
    gr.push([]);
  }
 
  // Adjacency matrix
  let edge = [];
 
  // Initializing the adjacency matrix
  for (let k = 0; k < MAX; k++) {
    edge.push([]);
    for (let l = 0; l < MAX; l++) {
      edge[k].push(0);
    }
  }
 
  // Creating the adjacency matrix
  for (let i = 0; i < n; i++) {
    for (let j = 0; j < m; j++) {
      if (i + 1 < n && edge[f(arr[i][j])][f(arr[i + 1][j])] === 0) {
        gr[f(arr[i][j])].push(f(arr[i + 1][j]));
        edge[f(arr[i][j])][f(arr[i + 1][j])] = 1;
      }
 
      if (j - 1 >= 0 && edge[f(arr[i][j])][f(arr[i][j - 1])] === 0) {
        gr[f(arr[i][j])].push(f(arr[i][j - 1]));
        edge[f(arr[i][j])][f(arr[i][j - 1])] = 1;
      }
 
      if (j + 1 < m && edge[f(arr[i][j])][f(arr[i][j + 1])] === 0) {
        gr[f(arr[i][j])].push(f(arr[i][j + 1]));
        edge[f(arr[i][j])][f(arr[i][j + 1])] = 1;
      }
 
      if (i - 1 >= 0 && edge[f(arr[i][j])][f(arr[i - 1][j])] === 0) {
        gr[f(arr[i][j])].push(f(arr[i - 1][j]));
        edge[f(arr[i][j])][f(arr[i - 1][j])] = 1;
      }
    }
  }
 
  // Queue to perform BFS
  let q = [];
  q.push(arr[0][0].charCodeAt(0) - 'a'.charCodeAt(0));
 
  // Visited array
  let v = [];
  for (let i = 0; i < MAX; i++) {
    v.push(0);
  }
 
  // To store the depth of BFS
  let d = 0;
 
// BFS
while (q.length > 0) {
// Number of elements in the current level
let cnt = q.length;
 
// Inner loop
while (cnt > 0) {
cnt--;
 
 
// Current element
let curr = q[0];
 
// Popping queue
q.shift();
 
// 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 === (arr[n - 1][m - 1].charCodeAt(0) - 'a'.charCodeAt(0))) return d;
 
// Iterating through the current node
for (let it of gr[curr]) {
  q.push(it);
}
}
 
// Updating the depth
d++;
}
 
return -1;
};
 
// Driver code
let arr = ['abc', 'def', 'gbi'];
console.log(findMinCost(arr));


Output: 

2

 

Time Complexity: O(N * M).
Auxiliary Space: O(N * M). 



Last Updated : 10 Feb, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads