Skip to content
Related Articles

Related Articles

Improve Article

Lexicographically largest prime path from top-left to bottom-right in a matrix

  • Difficulty Level : Hard
  • Last Updated : 09 Dec, 2020

Given a m x n matrix of positive integers. The task is to find the number of paths from the top left of the matrix to the bottom right of the matrix such that each integer in the path is prime. 
Also, print the lexicographical largest path among all the path. A cell (a, b) is lexicographical larger than cell (c, d) either a > b or if a == b then b > d. From cell (x, y), you are allowed to move (x + 1, y), (x, y + 1), (x + 1, y + 1). 

Note: It is given that the top-left cell will always have a prime number.

Examples: 

Input: n = 3, m = 3 
m[][] = { { 2, 3, 7 }, 
{ 5, 4, 2 }, 
{ 3, 7, 11 } } 
Output: 
Number of paths: 4 
Lexicographical largest path: (1, 1) -> (2, 1) -> (3, 2) -> (3, 3)
There are four ways to reach (3, 3) from (1, 1). 
Path 1: (1, 1) (1, 2) (1, 3) (2, 3) (3, 3) 
Path 2: (1, 1) (1, 2) (2, 3) (3, 3) 
Path 3: (1, 1) (2, 1) (3, 1) (3, 2) (3, 3) 
Path 4: (1, 1) (2, 1) (3, 2) (3, 3) 
Lexicographical Order -> 4 > 3 > 2 > 1

Approach: The idea is to use Dynamic Programming to solve the problem. First, observe, a non-prime number in the matrix can be treated as an obstacle and a prime number can be treated as a cell that can be used in the path. So, we can use a sieve to identify the obstacle and convert the given matrix into a binary matrix where 0 indicates the obstacle and 1 indicates the valid path. 
So, we will define a 2D matrix, say dp[][], where d[i][j] indicate the number of path from cell (1, 1) to cell(i, j). Also, we can define dp[i][j] as,  



dp[i][j] = dp[i-1][j] + dp[i][j-1] + dp[i-1][j-1]

i.e sum of path from left cell, right cell and upper left diagonal (moves allowed).
To find the lexicographical largest path, we can use DFS (Depth-first search). Consider each cell as a node which is having three outgoing edges, one to the cell adjacent right, cell adjacent down, and cell diagonal to lower left. Now, we will travel using a depth-first search in a manner so that we get the lexicographical largest path. So, to get the lexicographical largest path, from the cell (x, y) we first try to travel to cell (x + 1, y + 1) (if no path possible from that cell) then try travel to cell (x + 1, y) and finally to (x, y + 1).

Below is the implementation of this approach:  

C++




// C++ implementation of above approach
#include <bits/stdc++.h>
using namespace std;
#define MAX 105
 
void sieve(int prime[])
{
    for (int i = 2; i * i <= MAX; i++) {
        if (prime[i] == 0) {
            for (int j = i * i; j <= MAX; j += i)
                prime[j] = 1;
        }
    }
}
 
// Depth First Search
void dfs(int i, int j, int k, int* q, int n, int m,
         int mappedMatrix[][MAX], int mark[][MAX],
                                  pair<int, int> ans[])
{
    // Return if cell contain non prime number or obstacle,
    // or going out of matrix or already visited the cell
    // or already found the lexicographical larget path
    if (mappedMatrix[i][j] == 0 || i > n
                         || j > m || mark[i][j] || (*q))
        return;
 
    // marking cell is already visited
    mark[i][j] = 1;
 
    // storing the lexicographical largest path index
    ans[k] = make_pair(i, j);
 
    // if reached the end of the matrix
    if (i == n && j == m) {
 
        // updating the final number of
        // steps in lexicographical largest path
        (*q) = k;
        return;
    }
 
    // moving diagonal (trying lexicographical largest path)
    dfs(i + 1, j + 1, k + 1, q, n, m, mappedMatrix, mark, ans);
 
    // moving cell right to current cell
    dfs(i + 1, j, k + 1, q, n, m, mappedMatrix, mark, ans);
 
    // moving cell down to current cell.
    dfs(i, j + 1, k + 1, q, n, m, mappedMatrix, mark, ans);
}
 
// Print lexicographical largest prime path
void lexicographicalPath(int n, int m, int mappedMatrix[][MAX])
{
    // to count the number of step in
    // lexicographical largest prime path
    int q = 0;
 
    // to store the lexicographical
    // largest prime path index
    pair<int, int> ans[MAX];
 
    // to mark if the cell is already traversed or not
    int mark[MAX][MAX];
 
    // traversing by DFS
    dfs(1, 1, 1, &q, n, m, mappedMatrix, mark, ans);
 
    // printing the lexicographical largest prime path
    for (int i = 1; i <= q; i++)
        cout << ans[i].first << " " << ans[i].second << "\n";
}
 
// Return the number of prime path in ther matrix.
void countPrimePath(int mappedMatrix[][MAX], int n, int m)
{
    int dp[MAX][MAX] = { 0 };
    dp[1][1] = 1;
 
    // for each cell
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            // If on the top row or leftmost column,
            // there is no path there.
            if (i == 1 && j == 1)
                continue;
 
            dp[i][j] = (dp[i - 1][j] + dp[i][j - 1]
                        + dp[i - 1][j - 1]);
 
            // If non prime number
            if (mappedMatrix[i][j] == 0)
                dp[i][j] = 0;
        }
    }
 
    cout << dp[n][m] << "\n";
}
 
// Finding the matrix mapping by considering
// non prime number as obstacle and prime number be valid path.
void preprocessMatrix(int mappedMatrix[][MAX],
                      int a[][MAX], int n, int m)
{
    int prime[MAX];
 
    // Sieve
    sieve(prime);
 
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            // If prime
            if (prime[a[i][j]] == 0)
                mappedMatrix[i + 1][j + 1] = 1;
 
            // if non prime
            else
                mappedMatrix[i + 1][j + 1] = 0;
        }
    }
}
 
// Driver code
int main()
{
    int n = 3;
    int m = 3;
    int a[MAX][MAX] = { { 2, 3, 7 },
                        { 5, 4, 2 },
                        { 3, 7, 11 } };
 
    int mappedMatrix[MAX][MAX] = { 0 };
 
    preprocessMatrix(mappedMatrix, a, n, m);
 
    countPrimePath(mappedMatrix, n, m);
 
    lexicographicalPath(n, m, mappedMatrix);
 
    return 0;
}

Python3




# Python3 implementation of above approach
MAX = 105
  
def sieve():
     
    i = 2
     
    while(i * i < MAX):       
        if (prime[i] == 0):           
            for j in range(i * i,
                           MAX, i):           
                prime[j] = 1;       
        i += 1   
         
# Depth First Search
def dfs(i, j, k,
        q, n,  m):
 
    # Return if cell contain non
    # prime number or obstacle,
    # or going out of matrix or
    # already visited the cell
    # or already found the
    # lexicographical larget path
    if (mappedMatrix[i][j] == 0 or
        i > n or j > m or mark[i][j] or
        q != 0):
        return q;
  
    # marking cell is already
    # visited
    mark[i][j] = 1;
  
    # storing the lexicographical
    # largest path index
    ans[k] = [i, j]
  
    # if reached the end of
    # the matrix
    if (i == n and j == m):
  
        # updating the final number
        # of steps in lexicographical
        # largest path
        q = k;
        return q;
     
  
    # moving diagonal (trying lexicographical
    # largest path)
    q = dfs(i + 1, j + 1, k + 1, q, n, m);
  
    # moving cell right to current cell
    q = dfs(i + 1, j, k + 1, q, n, m);
  
    # moving cell down to current cell.
    q = dfs(i, j + 1, k + 1, q, n, m);
     
    return q
  
# Print lexicographical largest
# prime path
def lexicographicalPath(n, m):
 
    # To count the number of step
    # in lexicographical largest
    # prime path
    q = 0;
     
    global ans, mark
     
    # To store the lexicographical
    # largest prime path index
    ans = [[0, 0] for i in range(MAX)]
  
    # To mark if the cell is already
    # traversed or not
    mark = [[0 for j in range(MAX)]
               for i in range(MAX)]
  
    # traversing by DFS
    q = dfs(1, 1, 1, q, n, m);
  
    # printing the lexicographical
    # largest prime path
    for i in range(1, q + 1):
        print(str(ans[i][0]) + ' ' +
              str(ans[i][1]))
     
  
# Return the number of prime
# path in ther matrix.
def countPrimePath(n, m):
     
    global dp
     
    dp = [[0 for j in range(MAX)]
             for i in range(MAX)]
 
    dp[1][1] = 1;
  
    # for each cell
    for i in range(1, n + 1):
        for j in range(1, m + 1):
     
            # If on the top row or
            # leftmost column, there
            # is no path there.
            if (i == 1 and j == 1):
                continue;
  
            dp[i][j] = (dp[i - 1][j] +
                        dp[i][j - 1] +
                        dp[i - 1][j - 1]);
  
            # If non prime number
            if (mappedMatrix[i][j] == 0):
                dp[i][j] = 0;
     
    print(dp[n][m])   
  
# Finding the matrix mapping by
# considering non prime number
# as obstacle and prime number
# be valid path.
def preprocessMatrix(a, n, m):
     
    global prime
    prime = [0 for i in range(MAX)]
  
    # Sieve
    sieve();
     
    for i in range(n):
        for j in range(m):
         
            # If prime
            if (prime[a[i][j]] == 0):
                mappedMatrix[i + 1][j + 1] = 1;
  
            # if non prime
            else:
                mappedMatrix[i + 1][j + 1] = 0;
         
# Driver code
if __name__ == "__main__":
     
    n = 3;
    m = 3;
    a = [[ 2, 3, 7 ],
         [ 5, 4, 2 ],
         [ 3, 7, 11 ]];
     
    mappedMatrix = [[0 for j in range(MAX)]
                       for i in range(MAX)]
  
    preprocessMatrix(a, n, m);
  
    countPrimePath(n, m);
  
    lexicographicalPath(n, m);
  
# This code is contributed by Rutvik_56

C#




// C# implementation of above approach
using System;
using System.Collections;
using System.Collections.Generic;
 
class GFG{
 
static int MAX = 105;
  
static void sieve(int []prime)
{
    for(int i = 2; i * i < MAX; i++)
    {
        if (prime[i] == 0)
        {
            for (int j = i * i; j < MAX; j += i)
                prime[j] = 1;
        }
    }
}
 
class pair
{
    public int first,second;
     
    public pair(int first, int second)
    {
        this.first = first;
        this.second = second;
    }
}
  
// Depth First Search
static void dfs(int i, int j, int k,
            ref int q, int n, int m,
                int [,]mappedMatrix,
                int [,]mark, pair []ans)
{
     
    // Return if cell contain non prime
    // number or obstacle, or going out
    // of matrix or already visited the
    // cell or already found the
    // lexicographical larget path
    if ((mappedMatrix[i, j] == 0 ? true : false) ||
                          (i > n ? true : false) ||
                          (j > m ? true : false) ||
                (mark[i, j] != 0 ? true : false) ||
                         (q != 0 ? true : false))
        return;
  
    // Marking cell is already visited
    mark[i, j] = 1;
     
    // Storing the lexicographical
    // largest path index
    ans[k] = new pair(i, j);
     
    // If reached the end of the matrix
    if (i == n && j == m)
    {
         
        // Updating the final number of
        // steps in lexicographical
        // largest path
        (q) = k;
        return;
    }
     
    // Moving diagonal (trying
    // lexicographical largest path)
    dfs(i + 1, j + 1, k + 1, ref q,
        n, m, mappedMatrix, mark, ans);
  
    // Moving cell right to current cell
    dfs(i + 1, j, k + 1, ref q,
        n, m, mappedMatrix, mark, ans);
  
    // Moving cell down to current cell.
    dfs(i, j + 1, k + 1, ref q,
        n, m, mappedMatrix, mark, ans);
}
  
// Print lexicographical largest prime path
static void lexicographicalPath(int n, int m,
                                int [,]mappedMatrix)
{
     
    // To count the number of step in
    // lexicographical largest prime path
    int q = 0;
     
    // To store the lexicographical
    // largest prime path index
    pair []ans = new pair[MAX];
  
    // To mark if the cell is already
    // traversed or not
    int [,]mark = new int[MAX, MAX];
  
    // Traversing by DFS
    dfs(1, 1, 1, ref q, n,
        m, mappedMatrix, mark, ans);
  
    // Printing the lexicographical
    // largest prime path
    for(int i = 1; i <= q; i++)
        Console.WriteLine(ans[i].first + " " +
                          ans[i].second);
}
  
// Return the number of prime
// path in ther matrix.
static void countPrimePath(int [,]mappedMatrix,
                           int n, int m)
{
    int [,]dp = new int[MAX, MAX];
     
    for(int i = 0; i < MAX; i++)
    {
        for(int j = 0; j < MAX; j++)
        {
            dp[i, j] = 0;
        }
    }
     
    dp[1, 1] = 1;
  
    // For each cell
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
             
            // If on the top row or leftmost
            // column, there is no path there.
            if (i == 1 && j == 1)
                continue;
  
            dp[i, j] = (dp[i - 1, j] + dp[i, j - 1] +
                        dp[i - 1, j - 1]);
  
            // If non prime number
            if (mappedMatrix[i, j] == 0)
                dp[i, j] = 0;
        }
    }
    Console.WriteLine(dp[n, m]);
}
  
// Finding the matrix mapping by considering
// non prime number as obstacle and prime
// number be valid path.
static void preprocessMatrix(int [,]mappedMatrix,
                             int [,]a, int n, int m)
{
    int []prime = new int[MAX];
     
    // Sieve
    sieve(prime);
  
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < m; j++)
        {
             
            // If prime
            if (prime[a[i, j]] == 0)
                mappedMatrix[i + 1, j + 1] = 1;
  
            // If non prime
            else
                mappedMatrix[i + 1, j + 1] = 0;
        }
    }
}
  
// Driver code
public static void Main(string []args)
{
    int n = 3;
    int m = 3;
    int [,]a = new int[3, 3]{ { 2, 3, 7 },
                              { 5, 4, 2 },
                              { 3, 7, 11 } };
  
    int [,]mappedMatrix = new int[MAX, MAX];
     
    for(int i = 0; i < MAX; i++)
    {
        for(int j = 0; j < MAX; j++)
        {
            mappedMatrix[i, j] = 0;
        }
    }
     
    preprocessMatrix(mappedMatrix, a, n, m);
  
    countPrimePath(mappedMatrix, n, m);
     
    lexicographicalPath(n, m, mappedMatrix);
}
}
 
// This code is contributed by pratham76
Output: 
4
1 1
2 1
3 2
3 3

 

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.




My Personal Notes arrow_drop_up
Recommended Articles
Page :