Skip to content
Related Articles

Related Articles

Minimum sum falling path in a NxN grid

Improve Article
Save Article
  • Difficulty Level : Medium
  • Last Updated : 06 Sep, 2022
Improve Article
Save Article

Given an square array A of integers of size NxN. The task is to find the minimum sum of a falling path through A.
A falling path will starts at any element in the first row and ends in last row. It chooses one element from each next row. The next row’s choice must be in a column that is different from the previous row’s column by at most one.

Examples: 

Input: N = 2
mat[2][2] = 
{{5, 10},
{25, 15}}
Output: 20
Selected elements are 5, 15.

Input: N = 3
mat[3][3] =
{{1, 2, 3},
{ 4, 5, 6},
{ 7, 8, 9}}
Output: 12
Selected elements are 1, 4, 7.

Approach: This problem has an optimal substructure, meaning that the solutions to sub-problems can be used to solve larger instances of this problem. This makes dynamic programming came into existence.

Let dp[R][C] be the minimum total weight of a falling path starting at [R, C] in first row and reaching to the bottom row of A.
Then, dp[R][C] = A[R][C] + min(dp[R+1, C-1], dp[R+1, C], dp[R+1, C+1])          , and the answer is minimum value of first row i:e \underset{C}{min}\; dp(0, C)          .
We would make an auxiliary array dp to cache intermediate values dp[R][C]. However, we will use A to cache these values. Our goal is to transform the values of A into the values of dp.
We begins processing each row, starting with the second last row. We set A[R][C] = min(A[R+1, C-1], A[R+1, C], A[R+1, C+1])          , handling boundary conditions gracefully.

Explanation of above Approach: 

Let’s look at the recursion a little more to get a handle on why it works. For an array like A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]], imagine you are at (1, 0) (A[1][0] = 4). You can either go to (2, 0) and get a weight of 7, or (2, 1) and get a weight of 8. Since 7 is lower, we say that the minimum total weight at (1, 0) is dp(1, 0) = 5 + 7 (7 for the original A[R][C].)

After visiting (1, 0), (1, 1), and (1, 2), A [which is storing the values of our dp], looks like [[1, 2, 3], [11, 12, 14], [7, 8, 9]]. We do this procedure again by visiting (0, 0), (0, 1), (0, 2).
We get A=\begin{bmatrix} 12 & 13 & 15\\ 11 & 12& 14\\ 7 & 8 & 9 \end{bmatrix}          , and the final answer is min(A[0][C]) = 12 for all C in range 0 to n.

Below is the implementation of above approach. 

C++




// C++ Program to minimum required sum
#include <bits/stdc++.h>
using namespace std;
 
const int n = 3;
 
// Function to return minimum path falling sum
int minFallingPathSum(int (&A)[n][n])
{
 
    // R = Row and C = Column
    // We begin from second last row and keep
    // adding maximum sum.
    for (int R = n - 2; R >= 0; --R) {
        for (int C = 0; C < n; ++C) {
 
            // best = min(A[R+1][C-1], A[R+1][C], A[R+1][C+1])
            int best = A[R + 1][C];
            if (C > 0)
                best = min(best, A[R + 1][C - 1]);
            if (C + 1 < n)
                best = min(best, A[R + 1][C + 1]);
            A[R][C] = A[R][C] + best;
        }
    }
 
    int ans = INT_MAX;
    for (int i = 0; i < n; ++i)
        ans = min(ans, A[0][i]);
    return ans;
}
 
// Driver program
int main()
{
 
    int A[n][n] = { { 1, 2, 3 },
                    { 4, 5, 6 },
                    { 7, 8, 9 } };
 
    // function to print required answer
    cout << minFallingPathSum(A);
 
    return 0;
}

Java




// Java Program to minimum required sum
 
import java.io.*;
 
class GFG {
static int n = 3;
 
// Function to return minimum path falling sum
static int minFallingPathSum(int A[][])
{
 
    // R = Row and C = Column
    // We begin from second last row and keep
    // adding maximum sum.
    for (int R = n - 2; R >= 0; --R) {
        for (int C = 0; C < n; ++C) {
 
            // best = min(A[R+1][C-1], A[R+1][C], A[R+1][C+1])
            int best = A[R + 1][C];
            if (C > 0)
                best = Math.min(best, A[R + 1][C - 1]);
            if (C + 1 < n)
                best = Math.min(best, A[R + 1][C + 1]);
            A[R][C] = A[R][C] + best;
        }
    }
 
    int ans = Integer.MAX_VALUE;
    for (int i = 0; i < n; ++i)
        ans = Math.min(ans, A[0][i]);
    return ans;
}
 
// Driver program
public static void main (String[] args) {
            int A[][] = { { 1, 2, 3 },
                    { 4, 5, 6 },
                    { 7, 8, 9 } };
 
    // function to print required answer
    System.out.println( minFallingPathSum(A));
    }
}
// This code is contributed by inder_verma..

Python 3




# Python3 Program to minimum
# required sum
import sys
 
n = 3
 
# Function to return minimum
# path falling sum
def minFallingPathSum(A) :
 
    # R = Row and C = Column
    # We begin from second last row and keep
    # adding maximum sum.
    for R in range(n - 2, -1, -1) :
        for C in range(n) :
 
            # best = min(A[R+1][C-1], A[R+1][C],
            # A[R+1][C+1])
            best = A[R + 1][C]
            if C > 0 :
                best = min(best, A[R + 1][C - 1])
            if C + 1 < n :
                best = min(best, A[R + 1][C + 1])
 
            A[R][C] = A[R][C] + best
 
    ans = sys.maxsize
 
    for i in range(n) :
        ans = min(ans, A[0][i])
         
    return ans
             
 
 
# Driver code
if __name__ == "__main__" :
 
    A = [ [ 1, 2, 3],
        [ 4, 5, 6],
        [ 7, 8, 9] ]
 
    # function to print required answer
    print(minFallingPathSum(A))
 
# This code is contributed by
# ANKITRAI1

C#




// C# Program to minimum required sum
 
using System;
 
class GFG {
static int n = 3;
 
// Function to return minimum path falling sum
static int minFallingPathSum(int[,] A)
{
 
    // R = Row and C = Column
    // We begin from second last row and keep
    // adding maximum sum.
    for (int R = n - 2; R >= 0; --R) {
        for (int C = 0; C < n; ++C) {
 
            // best = min(A[R+1,C-1], A[R+1,C], A[R+1,C+1])
            int best = A[R + 1,C];
            if (C > 0)
                best = Math.Min(best, A[R + 1,C - 1]);
            if (C + 1 < n)
                best = Math.Min(best, A[R + 1,C + 1]);
            A[R,C] = A[R,C] + best;
        }
    }
 
    int ans = int.MaxValue;
    for (int i = 0; i < n; ++i)
        ans = Math.Min(ans, A[0,i]);
    return ans;
}
 
// Driver program
public static void Main () {
            int[,] A = { { 1, 2, 3 },
                    { 4, 5, 6 },
                    { 7, 8, 9 } };
 
    // function to print required answer
    Console.WriteLine( minFallingPathSum(A));
    }
}
// This code is contributed by Subhadeep..

Javascript




<script>
    // Javascript Program to minimum required sum   
    let n = 3;
  
    // Function to return minimum path falling sum
    function minFallingPathSum(A)
    {
 
        // R = Row and C = Column
        // We begin from second last row and keep
        // adding maximum sum.
        for (let R = n - 2; R >= 0; --R) {
            for (let C = 0; C < n; ++C) {
 
                // best = min(A[R+1][C-1], A[R+1][C], A[R+1][C+1])
                let best = A[R + 1][C];
                if (C > 0)
                    best = Math.min(best, A[R + 1][C - 1]);
                if (C + 1 < n)
                    best = Math.min(best, A[R + 1][C + 1]);
                A[R][C] = A[R][C] + best;
            }
        }
 
        let ans = Number.MAX_VALUE;
        for (let i = 0; i < n; ++i)
            ans = Math.min(ans, A[0][i]);
        return ans;
    }
     
    let A = [ [ 1, 2, 3 ],
             [ 4, 5, 6 ],
             [ 7, 8, 9 ] ];
  
    // function to print required answer
    document.write(minFallingPathSum(A));
     
    // This code is contributed by divyesh072019.
</script>

Output

12

Time Complexity: O(N2)

Top-Down Approach:

  1. Compute a function and follow up the recursive solution.
  2. Consider all the base conditions.
  3. Start moving in all the possible directions as mentioned in the question.
  4. When reached the end corner of the grid, simply consider the minimum fall path sum.
  5. Return the minimum falling path sum.

Below is the implementation of the above approach:

C++




// C++ Program to minimum required sum
#include <bits/stdc++.h>
using namespace std;
  
const int n = 3;
  
// Function to return minimum path falling sum
int helper(int i, int j, int A[n][n],vector<vector<int>>&dp){
        if(j<0 || j>=n)
            return 1e9;
         
        if(i==0)
            return A[0][j];
         
        if(dp[i][j]!=-1)
            return dp[i][j];
         
        int a = A[i][j] + helper(i-1,j,A,dp);
        int b = A[i][j] + helper(i-1,j-1,A,dp);
        int c = A[i][j] + helper(i-1,j+1,A,dp);
         
        return dp[i][j] = min(a,min(b,c));
    }
     
    int minFallingPathSum(int A[n][n]) {
         
         
        vector<vector<int>> dp(n,vector<int>(n,-1));
         
         int res=1e9;
         for(int k=0;k<n;k++){
           res=min(res,helper(n-1,k,A,dp))  ;
         }
                 
        return res;
    }
  
// Driver program
int main()
{
  
    int A[n][n] = { { 1, 2, 3 },
                    { 4, 5, 6 },
                    { 7, 8, 9 } };
  
    // function to print required answer
   
    cout << minFallingPathSum(A);
  
    return 0;
}
//This code was contributed by Sanskar

Java




import java.io.*;
  
class GFG {
static int n = 3;
  
// Function to return minimum path falling sum
public static int minFallingPathSum(int[][] matrix) {
        int rows = matrix.length;
        int columns = matrix[0].length;
        Integer[][] dp = new Integer[rows][columns];
        int ans = Integer.MAX_VALUE;
        for(int column = 0; column < columns; column += 1) {
            ans = Math.min(ans, minPathSum(rows - 1, column, matrix, dp));
        }
        return ans;
    }
    private static int minPathSum(int row, int column, int[][] matrix, Integer[][] dp) {
        if(row < 0) {
            return 0;
        }
        if(column < 0 || column >= matrix[0].length) {
            return 100000000;
        }
        if(dp[row][column] != null) {
            return dp[row][column];
        }
        int ans = matrix[row][column] + Math.min(minPathSum(row - 1, column - 1, matrix, dp), Math.min(minPathSum(row - 1, column, matrix, dp), minPathSum(row - 1, column + 1, matrix, dp)));
        return dp[row][column] = ans;
    }
  
// Driver program
public static void main (String[] args) {
            int A[][] = { { 1, 2, 3 },
                    { 4, 5, 6 },
                    { 7, 8, 9 } };
     
     
    // function to print required answer
    System.out.println( minFallingPathSum(A));
    }
}
//This code was contributed by Sanskar

Python3




# Python3 program for the above approach
 
def fallingpathsum(grid, row, col, Row, Col, dp):
 
    # Base condition
    if row == Row-1 and col == Col-1
        return grid[row][col]
       
    # Base condition
    if row > Row-1 or col > Col-1
        return 0
       
    # Respective directions
    rightdown = fallingpathsum(grid, row+1, col, Row, Col, dp)
    rdd = fallingpathsum(grid, row+1, col+1, Row, Col, dp)
    ldd = fallingpathsum(grid, row+1, col-1, Row, Col, dp)
     
     # Checking for duplicates
    if dp[row][col] == -1:
        dp[row][col] = grid[row][col] + min(rightdown, ldd, rdd)
    return dp[row][col]
 
 
grid = [[1,2,3], [4,5,6],[7,8,9]]
Row = len(grid)
Col = len(grid[0])
dp = [[-1 for i in range(Row)]for _ in range(Col)]
print(fallingpathsum(grid, 0, 0, Row, Col, dp))
# CODE CONTRIBUTED BY RAMPRASAD KONDOJU

Output

12

Complexity Analysis:

  • Time Complexity: O(N2)
  • Space Complexity: O(N2)+O(N)

Bottom-up Approach:

Instead of using recursion, we can calculate Min. path if we keep on adding the minimum possible value for every element from the previous row. If we keep on doing this, at last we would be left with just one row containing all falling path sums. We return the min.

Implementation:

C++




// C++ Program to minimum required sum
#include <bits/stdc++.h>
using namespace std;
 
const int n = 3;
 
// Function to return minimum path falling sum
 
int minFallingPathSum(int A[n][n])
{
 
    int ans = 0;
    vector<vector<int> > dp(n, vector<int>(n, 0));
    for (int i = 0; i < n; i++) {
        int minimum = INT_MAX;
        for (int j = 0; j < n; j++) {
            if (i == 0) {
                dp[i][j] = A[i][j];
                minimum = min(minimum, dp[i][j]);
                continue;
            }
            int up = A[i][j];
            int left = A[i][j], right = A[i][j];
            up += dp[i - 1][j];
            if (j > 0) {
                left += dp[i - 1][j - 1];
            }
            else {
                left = INT_MAX;
            }
            if (j < n - 1) {
                right += dp[i - 1][j + 1];
            }
            else {
                right = INT_MAX;
            }
 
            dp[i][j] += min(left, min(right, up));
            minimum = min(minimum, dp[i][j]);
        }
 
        ans = minimum;
    }
    return ans;
}
 
// Driver program
int main()
{
 
    int A[n][n] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
 
    // function to print required answer
 
    cout << minFallingPathSum(A);
 
    return 0;
}

Java




// Java Program to minimum required sum
 
import java.io.*;
 
class GFG {
    static int n = 3;
 
    // Function to return minimum path falling sum
    static int minFallingPathSum(int A[][])
    {
 
        // corner case
        if (A == null || A.length == 0 || A[0].length == 0)
            return 0;
 
        int m = A.length;
        int n = A[0].length;
        int[][] M = new int[m][n];
        // M[i][j] represents the min
        // sum from top to A[i][j]
        // M[0][j] stays the same
        // M[i][j] = min(M[i - 1][j - 1], M[i - 1][j], M[i -
        // 1][j + 1]) + A[i][j]
 
        // copy the 1st row to M[0]
        for (int j = 0; j < n; j++) {
            M[0][j] = A[0][j];
        }
 
        for (int i = 1; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (j == 0) {
                    M[i][j] = Math.min(M[i - 1][j],
                                       M[i - 1][j + 1]);
                }
                else if (j == n - 1) {
                    M[i][j] = Math.min(M[i - 1][j - 1],
                                       M[i - 1][j]);
                }
                else {
                    M[i][j] = Math.min(M[i - 1][j - 1],
                                       M[i - 1][j]);
                    M[i][j] = Math.min(M[i][j],
                                       M[i - 1][j + 1]);
                }
                M[i][j] += A[i][j];
            }
        }
 
        int min = Integer.MAX_VALUE;
        for (int num : M[m - 1]) {
            min = Math.min(min, num);
        }
 
        return min;
    }
 
    // Driver program
    public static void main(String[] args)
    {
        int A[][]
            = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
 
        // function to print required answer
        System.out.println(minFallingPathSum(A));
    }
}

Output

12

Complexity Analysis:

  • Time Complexity: O(N2)
  • Space Complexity: O(N2)

My Personal Notes arrow_drop_up

Start Your Coding Journey Now!