Thursday, July 4, 2024
HomeData ModellingDynamic ProgrammingFind if path from top-left to bottom-right with sum X exists in...

Find if path from top-left to bottom-right with sum X exists in given Matrix

Given a matrix A[][] of size N * N, where each matrix element is either -1 or 1. One can move from (X, Y) to either  (X + 1, Y) or (X, Y + 1) but not out of the matrix. The task is to check whether a path exists from the top-left to the bottom-right corner such that the sum of all elements in the path is X.

Examples: 

Input: arr[][] = {{1, 1, 1, 1}, {-1, 1, -1, -1}, {-1, 1, -1, 1}, {-1, -1, 1, 1}}, X = 3
Output: Yes
Explanation:
One path will be : 
Cell 1: (0, 0), Sum = 1 now moving down to (1, 0)
Cell 2: (1, 0), Sum = 1 – 1 now moving right to (1, 1)
Cell 3: (1, 1), Sum = 1 – 1 + 1 now moving down to (2, 1)
Cell 4: (2, 1), Sum = 1 – 1 + 1 + 1 now moving down to (3, 1)
Cell 5: (3, 1), Sum = 1 – 1 + 1 + 1 – 1 now moving right to (3, 2)
Cell 6: (3, 2), Sum = 1 – 1 + 1 + 1 – 1 + 1 now moving right to (3, 3)
Cell 7: (3, 3), Sum = 1 – 1 + 1 + 1 – 1 + 1 + 1
The total sum is 3 which is equal to X Hence Print “Yes”. For a detailed explanation check the Efficient approach.

Input: arr[][] = {{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, X = 4
Output: No

Naive approach: The basic way to solve the problem is as follows:

Visit all paths and track their sum by using recursive brute force in exponential time. 

Time Complexity: O(2N * N)
Auxiliary Space: O(1)

Efficient Approach:  The above approach can be optimized based on the following idea

Let’s say minPathSum and maxPathSum are the maximum and minimum path sum from (0, 0) to (N-1, N-1) which can be calculated by Dynamic programming

  • dp[i][j] is minimum/maximum path sum at cell (i, j)
  • recurrence relation : dp[i][j] = min or max of (dp[i – 1][j], dp[i][j – 1]) + A[i][j]

In this problem most important thing is greedy observation below.

  • if number of cells from top-left to bottom-right is odd then all path sums of odd values can be generated in range [minPathSum, maxPathSum]
  • if number of cells from top-left to bottom-right are even then all path sum of even values can be generated in range [minPathSum, maxPathSum]

Follow the steps below to solve the problem:

  • Calculating minPathSum and maxPathSum using dynamic programming.
  • Calculating the number of cells from (1, 1) to (N, N) with the formula numberOfCells = 2 * N  – 1.
  • if X has the same parity(fact of being odd or even) as numberOfCells and X is in between range [minPathSum, maxPathSum] print “Yes” else print “No”.

Below is the implementation of the above approach:

C++




// C++ code to implement the approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to check whether paths
// exists from (1, 1) to (N, N) such
// that its sum is X
void isReachable(vector<vector<int> > A, int N, int X)
{
 
    // DP table for finding maximum and
    // minimum path sum
    vector<vector<vector<int> > > dp(
        N, vector<vector<int> >(N, vector<int>(2, 0)));
 
    // Base Case
    dp[0][0][0] = A[0][0];
    dp[0][0][1] = A[0][0];
 
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
 
            // Base Case
            if (i == 0 and j == 0)
                continue;
 
            // When coming from left is not
            // possible
            if (i == 0) {
                dp[i][j][0] = dp[i][j - 1][0] + A[i][j - 1];
                dp[i][j][1] = dp[i][j - 1][1] + A[i][j - 1];
            }
 
            // When coming from Left is not
            // possible
            else if (j == 0) {
                dp[i][j][0] = dp[i - 1][j][0] + A[i - 1][j];
                dp[i][j][1] = dp[i - 1][j][1] + A[i - 1][j];
            }
 
            // When Both coming from Left and Up
            // possible
            else {
                dp[i][j][0]
                    = min(dp[i - 1][j][0] + A[i - 1][j],
                          dp[i][j - 1][0] + A[i][j - 1]);
                dp[i][j][1]
                    = max(dp[i - 1][j][1] + A[i - 1][j],
                          dp[i][j - 1][1] + A[i][j - 1]);
            }
        }
    }
 
    // Minimum Path sum from (1, 1) to (N, N)
    int minimumPathSum = dp[N - 1][N - 1][0];
 
    // Maximum Path sum from (1, 1) to (N, N)
    int maximumPathSum = dp[N - 1][N - 1][1];
 
    // Number of cells in path from (1, 1) to (N, N)
    int numberOfCells = 2 * N - 1;
 
    // Parity of both numberOfCells from (1, 1)
    // to (N, N) and X should be same and X
    // should be in between range from
    // minmumPathSum and maximumPathSum
    if (numberOfCells % 2 == X % 2 && minimumPathSum <= X
        && maximumPathSum >= X)
 
        cout << "Yes" << endl;
    else
        cout << "No" << endl;
}
 
// Driver Code
int main()
{
    // Input 1
    vector<vector<int> > A{ { 1, 1, 1, 1 },
                            { -1, 1, -1, -1 },
                            { -1, 1, -1, 1 },
                            { -1, -1, 1, 1 } };
    int N = A.size();
    int X = 3;
 
    // Function Call
    isReachable(A, N, X);
 
    // Input 2
    vector<vector<int> > A1{ { 1, 1, 1 },
                             { 1, 1, 1 },
                             { 1, 1, 1 } };
    int N1 = A1.size();
    int X1 = 4;
 
    // Function Call
    isReachable(A1, N1, X1);
    return 0;
}


Java




// Java code to implement the approach
 
class GFG {
 
    // Function to check whether paths exists from (1, 1) to
   // (N, N) such that its sum is X
    public static void isReachable(int[][] A, int N, int X) {
 
        // DP table for finding maximum and minimum path sum
        int[][][] dp = new int[N][N][2];
 
        // Base Case
        dp[0][0][0] = A[0][0];
        dp[0][0][1] = A[0][0];
 
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
 
                // Base Case
                if (i == 0 && j == 0) {
                    continue;
                }
 
                // When coming from left is not possible
                if (i == 0) {
                    dp[i][j][0] = dp[i][j - 1][0] + A[i][j - 1];
                    dp[i][j][1] = dp[i][j - 1][1] + A[i][j - 1];
                }
 
                // When coming from Left is not possible
                else if (j == 0) {
                    dp[i][j][0] = dp[i - 1][j][0] + A[i - 1][j];
                    dp[i][j][1] = dp[i - 1][j][1] + A[i - 1][j];
                }
 
                // When Both coming from Left and Up possible
                else {
                    dp[i][j][0]
                        = Math.min(dp[i - 1][j][0] + A[i - 1][j],
                                   dp[i][j - 1][0] + A[i][j - 1]);
                    dp[i][j][1]
                        = Math.max(dp[i - 1][j][1] + A[i - 1][j],
                                   dp[i][j - 1][1] + A[i][j - 1]);
                }
            }
        }
 
        // Minimum Path sum from (1, 1) to (N, N)
        int minimumPathSum = dp[N - 1][N - 1][0];
 
        // Maximum Path sum from (1, 1) to (N, N)
        int maximumPathSum = dp[N - 1][N - 1][1];
 
        // Number of cells in path from (1, 1) to (N, N)
        int numberOfCells = 2 * N - 1;
 
        // Parity of both numberOfCells from (1, 1)
        // to (N, N) and X should be same and X
        // should be in between range from
        // minmumPathSum and maximumPathSum
        if (numberOfCells % 2 == X % 2 && minimumPathSum <= X &&
            maximumPathSum >= X) {
            System.out.println("Yes");
 
        } else {
            System.out.println("No");
        }
    }
 
 
    // Driver Code
    public static void main(String[] args) {
        int[][] A = { { 1, 1, 1, 1 },
            { -1, 1, -1, -1 },
            { -1, 1, -1, 1 },
            { -1, -1, 1, 1 }
        };
 
        int N = 4;
        int X = 3;
 
        // Function Call
        isReachable(A, N, X);
 
        // Input 2
        int[][] A1 = { { 1, 1, 1, 1 },
            { -1, 1, -1, -1 },
            { -1, 1, -1, 1 },
            { -1, -1, 1, 1 }
        };
 
        int N1 = 3;
        int X1 = 4;
 
        // Function Call
        isReachable(A1, N1, X1);
    }
}


Python3




# Python code to implement the approach
import math
 
# Function to check whether paths exists from
# (1, 1) to (N, N) such that its sum is x
def is_reachable(A, N, X):
   
    # DP table for finding maximum and minimum path sum
    dp = [[[0 for i in range(2)] for j in range(N)] for k in range(N)]
 
    # Base Case
    dp[0][0][0] = A[0][0]
    dp[0][0][1] = A[0][0]
 
    for i in range(N):
        for j in range(N):
            # Base Case
            if i == 0 and j == 0:
                continue
 
            # When coming from left is not possible
            elif i == 0:
                dp[i][j][0] = dp[i][j-1][0] + A[i][j-1]
                dp[i][j][1] = dp[i][j-1][1] + A[i][j-1]
 
            # When coming from Left is not possible
            elif j == 0:
                dp[i][j][0] = dp[i-1][j][0] + A[i-1][j]
                dp[i][j][1] = dp[i-1][j][1] + A[i-1][j]
 
            # When Both coming from Left and Up possible
            else:
                dp[i][j][0] = min(dp[i-1][j][0] + A[i-1][j], dp[i][j-1][0] + A[i][j-1])
                dp[i][j][1] = max(dp[i-1][j][1] + A[i-1][j], dp[i][j-1][1] + A[i][j-1])
 
    # Minimum Path sum from (1, 1) to (N, N)
    minimum_path_sum = dp[N-1][N-1][0]
 
    # Maximum Path sum from (1, 1) to (N, N)
    maximum_path_sum = dp[N-1][N-1][1]
 
    # Number of cells in path from (1, 1) to (N, N)
    number_of_cells = 2 * N - 1
 
    # Parity of both numberOfCells from (1, 1)
    # to (N, N) and X should be same and X
    # should be in between range from
    # minmumPathSum and maximumPathSum
    if number_of_cells % 2 == X % 2 and minimum_path_sum <= X and maximum_path_sum >= X:
        print("Yes")
    else:
        print("No")
 
# Driver Code
A = [[1, 1, 1, 1], [-1, 1, -1, -1], [-1, 1, -1, 1], [-1, -1, 1, 1]]
N = 4
X = 3
 
# Function Call
is_reachable(A, N, X)
 
# Input 2
A1 = [[1, 1, 1, 1], [-1, 1, -1, -1], [-1, 1, -1, 1], [-1, -1, 1, 1]]
N1 = 3
X1 = 4
 
# Function Call
is_reachable(A1, N1, X1)
 
# This code is contributed by lokeshmvs21.


C#




// C# code to implement the approach
using System;
using System.Collections.Generic;
 
class GFG {
 
  // Function to check whether paths
  // exists from (1, 1) to (N, N) such
  // that its sum is X
  static void isReachable(List<List<int> > A, int N, int X)
  {
 
    // DP table for finding maximum and
    // minimum path sum
    int[,,]dp=new int[N,N,2];
    for(int i=0; i<N; i++)
    {
      for(int j=0; j<N; j++)
      {
        for(int k=0; k<2; k++)
          dp[i,j,k]=0;
      }
    }
 
    // Base Case
    dp[0,0,0] = A[0][0];
    dp[0,0,1] = A[0][0];
 
    for (int i = 0; i < N; i++) {
      for (int j = 0; j < N; j++) {
 
        // Base Case
        if (i == 0 && j == 0)
          continue;
 
        // When coming from left is not
        // possible
        if (i == 0) {
          dp[i,j,0] = dp[i,j - 1,0] + A[i][j - 1];
          dp[i,j,1] = dp[i,j - 1,1] + A[i][j - 1];
        }
 
        // When coming from Left is not
        // possible
        else if (j == 0) {
          dp[i,j,0] = dp[i - 1,j,0] + A[i - 1][j];
          dp[i,j,1] = dp[i - 1,j,1] + A[i - 1][j];
        }
 
        // When Both coming from Left and Up
        // possible
        else {
          dp[i,j,0]
            = Math.Min(dp[i - 1,j,0] + A[i - 1][j],
                       dp[i,j - 1,0] + A[i][j - 1]);
          dp[i,j,1]
            = Math.Max(dp[i - 1,j,1] + A[i - 1][j],
                       dp[i,j - 1,1] + A[i][j - 1]);
        }
      }
    }
 
    // Minimum Path sum from (1, 1) to (N, N)
    int minimumPathSum = dp[N - 1,N - 1,0];
 
    // Maximum Path sum from (1, 1) to (N, N)
    int maximumPathSum = dp[N - 1,N - 1,1];
 
    // Number of cells in path from (1, 1) to (N, N)
    int numberOfCells = 2 * N - 1;
 
    // Parity of both numberOfCells from (1, 1)
    // to (N, N) and X should be same and X
    // should be in between range from
    // minmumPathSum and maximumPathSum
    if (numberOfCells % 2 == X % 2 && minimumPathSum <= X
        && maximumPathSum >= X)
 
      Console.Write("Yes\n");
    else
      Console.Write("No\n");
  }
 
  // Driver Code
  public static void Main()
  {
    // Input 1
    List<List<int> > A=new List<List<int>>();
    A.Add(new List<int>{ 1, 1, 1, 1 });
    A.Add(new List<int>{ -1, 1, -1, -1 });
    A.Add(new List<int>{ -1, 1, -1, 1 });
    A.Add(new List<int>{ -1, -1, 1, 1 });
    int N = A.Count;
    int X = 3;
 
    // Function Call
    isReachable(A, N, X);
 
    // Input 2
    List<List<int> > A1=new List<List<int>>();
    A1.Add(new List<int> { 1, 1, 1 });
    A1.Add(new List<int>{ 1, 1, 1 });
    A1.Add(new List<int>{ 1, 1, 1 });
    int N1 = A1.Count;
    int X1 = 4;
 
    // Function Call
    isReachable(A1, N1, X1);
  }
}
 
// This code is contributed by poojaagarwal2.


Javascript




// JavaScript code to implement the approach
 
// Function to check whether paths
// exists from (1, 1) to (N, N) such
// that its sum is X
function isReachable(A, N, X) {
  // DP table for finding maximum and
  // minimum path sum
  let dp = new Array(N);
  for (let i = 0; i < N; i++) {
    dp[i] = new Array(N);
    for (let j = 0; j < N; j++) {
      dp[i][j] = new Array(2).fill(0);
    }
  }
 
  // Base Case
  dp[0][0][0] = A[0][0];
  dp[0][0][1] = A[0][0];
 
  for (let i = 0; i < N; i++) {
    for (let j = 0; j < N; j++) {
      // Base Case
      if (i === 0 && j === 0) continue;
 
      // When coming from left is not
      // possible
      if (i === 0) {
        dp[i][j][0] = dp[i][j - 1][0] + A[i][j - 1];
        dp[i][j][1] = dp[i][j - 1][1] + A[i][j - 1];
      }
      // When coming from Left is not
      // possible
      else if (j === 0) {
        dp[i][j][0] = dp[i - 1][j][0] + A[i - 1][j];
        dp[i][j][1] = dp[i - 1][j][1] + A[i - 1][j];
      }
      // When Both coming from Left and Up
      // possible
      else {
        dp[i][j][0] = Math.min(dp[i - 1][j][0] + A[i - 1][j],
        dp[i][j - 1][0] + A[i][j - 1]);
        dp[i][j][1] = Math.max(dp[i - 1][j][1] + A[i - 1][j],
        dp[i][j - 1][1] + A[i][j - 1]);
      }
    }
  }
 
  // Minimum Path sum from (1, 1) to (N, N)
  let minimumPathSum = dp[N - 1][N - 1][0];
 
  // Maximum Path sum from (1, 1) to (N, N)
  let maximumPathSum = dp[N - 1][N - 1][1];
 
  // Number of cells in path from (1, 1) to (N, N)
  let numberOfCells = 2 * N - 1;
 
  // Parity of both numberOfCells from (1, 1)
  // to (N, N) and X should be same and X
  // should be in between range from
  // minmumPathSum and maximumPathSum
  if (numberOfCells % 2 === X % 2 && minimumPathSum <= X &&
       maximumPathSum >= X) {
    console.log("Yes");
  } else {
    console.log("No");
  }
}
 
// Driver Code
let A = [ [ 1, 1, 1, 1 ],[ -1, 1, -1, -1 ],[ -1, 1, -1, 1 ],[ -1, -1, 1, 1 ] ];
 
 
    let N = A.length;
    let X = 3;
 
    // Function Call
    isReachable(A, N, X);
 
    // Input 2
    let A1= [ [ 1, 1, 1 ],[ 1, 1, 1 ],[ 1, 1, 1 ] ];
    let N1 = A1.length;
    let X1 = 4;
 
    // Function Call
    isReachable(A1, N1, X1);
     
// code by ksam24000


Output

Yes
No

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

Related Articles :

Feeling lost in the world of random DSA topics, wasting time without progress? It’s time for a change! Join our DSA course, where we’ll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!

Dominic Rubhabha Wardslaus
Dominic Rubhabha Wardslaushttps://neveropen.dev
infosec,malicious & dos attacks generator, boot rom exploit philanthropist , wild hacker , game developer,
RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments