Open In App
Related Articles

Maximum path sum when at most K elements can be picked from a row

Improve Article
Improve
Save Article
Save
Like Article
Like

Given a matrix mat[][] of size N * M and an integer K, the task is to find a path from the top-left cell (0, 0) to the bottom-right cell (N–1, M–1) of the given matrix such that:

  • One right and downward movement are allowed. i.e., from (i, j) to (i, j-1) and (i+1, j). 
  • Sum of the elements in the path is maximum and not more than K cells can be chosen from one row.

Examples:

Input: N = 3, M = 3, K = 2, mat = [[2, 10, 8], [8, 8, 8], [0, 1, 0]]
Output: 28
Explanation: The optimal way of choosing cells will be (0, 0) -> (0, 1) -> (1, 1) -> (1, 2) -> (2, 2). 

Input: N = 3, M = 3, K = 1, mat = [[0, 0, 4], [0, 5, 0], [3, 0, 2]]
Output: 7
Explanation: The optimal way of choosing cells will be (0, 0) -> (1, 0) -> (1, 1) -> (1, 2) -> (2, 2). 

 

Naive Approach: The easiest approach is to find all the possible paths from top-left to bottom-right and having not more than K cells from a single row. Calculate the maximum path sum among all of them.

Time Complexity: O(M+N-2CN-1)
Auxiliary Space: O(1)

Efficient Approach: The efficient approach to solve the problem is to use dynamic programming based on the following idea:

For any row consider that 1 to K number of elements are chosen from that row. 
For any cell (i, j) consider it to be a part of the path choosing l number of cells from that row. 
Create a 3D dp array where dp[i][j][l] store the calculated value when cell (i, j) is part of a path having l cells from that row. 

  • dp[i][j][l] depends on dp[i][j][l-1] and dp[i][j-1][l]
  • dp[i][j][0] depends on dp[i-1][j][l] for all value of l from 1 to K (because when row is changed no element from the new row is taken till now).

Follow the below steps to solve this problem :

  • Declare a 3D array (say dp) with size N * M * (K + 1).
  • Iterate over the given matrix:
    • Iterate over all the possible values of l in reverse order (from K-1 to 0):
      • Check if the current state of dp has a positive value.
      • Then update the dp array for (l + 1)-th state since we include the current value of the grid.
    • Again iterate over all the possible values of l:
      • Check if the current state of dp has a positive value.
      • Then update the downward cell of the current cell if it exists.
      • And also update the rightward cell of the current cell if it exists.
  • Declare an integer variable ans and initialize it with 0.
  • Iterate over all the possible values of l.
    • Update ans as max of itself and the dp[N-1][M-1][l].
  • Finally, return the ans.

Below is the implementation of the above approach :

C++




// C++ code to implement the approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the maximum path sum
int maximumProfits(int n, int m, int k,
                   vector<vector<int> >& grid)
{
 
    // Declare a -d array named “dp”
    // with size ‘N’ * ‘M’ * (‘K’ + 1).
    int dp[n][m][k + 1];
 
    // Initialize the "dp" array with INT_MIN.
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            for (int l = 0; l < k + 1; l++) {
                dp[i][j][l] = INT_MIN;
            }
        }
    }
 
    // Base case.
    dp[0][0][0] = 0;
 
    // Iterate over the grid.
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
 
            // Iterate over the possible
            // values of ‘l’ in reverse order.
            for (int l = k - 1; l >= 0; l--) {
 
                // If the current state
                // of “dp” has positive value
                if (dp[i][j][l] >= 0) {
 
                    // Update “dp” array for
                    //(‘l’ + 1)-th state since
                    // we include
                    // the current value
                    // of the grid.
                    dp[i][j][l + 1]
                        = max(dp[i][j][l + 1],
                              dp[i][j][l]
                                  + grid[i][j]);
                }
            }
 
            // Again iterate over
            // all possible values of ‘l’.
            for (int l = 0; l < k + 1; l++) {
 
                // If the current state
                // of “dp” has positive value
                if (dp[i][j][l] >= 0) {
 
                    // Update the downward cell
                    // of the current cell
                    // if it exists.
                    if (i + 1 < n) {
                        dp[i + 1][j][0] = max(
                            dp[i + 1][j][0],
                            dp[i][j][l]);
                    }
 
                    // Update the right cell
                    // of the current cell
                    // if it exists.
                    if (j + 1 < m) {
                        dp[i][j + 1][l] = max(
                            dp[i][j + 1][l],
                            dp[i][j][l]);
                    }
                }
            }
        }
    }
 
    // Declare an integer variable “ans” and
    // initialize it with 0.
    int ans = 0;
 
    // Iterate over all possible values of l
    for (int l = 0; l < k + 1; l++) {
 
        // Update ans as max of itself and
        // the dp value for (n -1, m - 1)th
        // cell  for the current value of l
        ans = max(ans, dp[n - 1][m - 1][l]);
    }
 
    // Return the “ans”.
    return ans;
}
 
// Driver code
int main()
{
    int N = 3, M = 3, K = 2;
    vector<vector<int> > mat = { { 2, 10, 8 },
                                 { 8, 8, 8 },
                                 { 0, 1, 0 } };
    cout << maximumProfits(N, M, K, mat);
    return 0;
}


Java




// JAVA code to implement the approach
import java.util.*;
class GFG {
 
  // Function to find the maximum path sum
  public static int
    maximumProfits(int n, int m, int k,
                   ArrayList<ArrayList<Integer> > grid)
  {
 
    // Declare a -d array named “dp”
    // with size ‘N’ * ‘M’ * (‘K’ + 1).
    int dp[][][] = new int[n][m][k + 1];
 
    // Initialize the "dp" array with INT_MIN.
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
        for (int l = 0; l < k + 1; l++) {
          dp[i][j][l] = Integer.MIN_VALUE;
        }
      }
    }
 
    // Base case.
    dp[0][0][0] = 0;
 
    // Iterate over the grid.
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
 
        // Iterate over the possible
        // values of ‘l’ in reverse order.
        for (int l = k - 1; l >= 0; l--) {
 
          // If the current state
          // of “dp” has positive value
          if (dp[i][j][l] >= 0) {
 
            // Update “dp” array for
            //(‘l’ + 1)-th state since
            // we include
            // the current value
            // of the grid.
            dp[i][j][l + 1] = Math.max(
              dp[i][j][l + 1],
              dp[i][j][l]
              + grid.get(i).get(j));
          }
        }
 
        // Again iterate over
        // all possible values of ‘l’.
        for (int l = 0; l < k + 1; l++) {
 
          // If the current state
          // of “dp” has positive value
          if (dp[i][j][l] >= 0) {
 
            // Update the downward cell
            // of the current cell
            // if it exists.
            if (i + 1 < n) {
              dp[i + 1][j][0]
                = Math.max(dp[i + 1][j][0],
                           dp[i][j][l]);
            }
 
            // Update the right cell
            // of the current cell
            // if it exists.
            if (j + 1 < m) {
              dp[i][j + 1][l]
                = Math.max(dp[i][j + 1][l],
                           dp[i][j][l]);
            }
          }
        }
      }
    }
 
    // Declare an integer variable “ans” and
    // initialize it with 0.
    int ans = 0;
 
    // Iterate over all possible values of l
    for (int l = 0; l < k + 1; l++) {
 
      // Update ans as max of itself and
      // the dp value for (n -1, m - 1)th
      // cell  for the current value of l
      ans = Math.max(ans, dp[n - 1][m - 1][l]);
    }
 
    // Return the “ans”.
    return ans;
  }
 
  // Driver code
  public static void main(String[] args)
  {
    int N = 3, M = 3, K = 2;
    ArrayList<ArrayList<Integer> > mat
      = new ArrayList<ArrayList<Integer> >();
    ArrayList<Integer> temp1 = new ArrayList<Integer>(
      Arrays.asList(2, 10, 8));
    ArrayList<Integer> temp2 = new ArrayList<Integer>(
      Arrays.asList(8, 8, 8));
    ArrayList<Integer> temp3 = new ArrayList<Integer>(
      Arrays.asList(0, 1, 0));
    mat.add(temp1);
    mat.add(temp2);
    mat.add(temp3);
    System.out.print(maximumProfits(N, M, K, mat));
  }
}
 
// This code is contributed by Taranpreet


Python3




# Python code to implement the approach
import sys
 
INT_MIN = -sys.maxsize - 1
 
# Function to find the maximum path sum
def maximumProfits(n, m, k,grid):
 
    global INT_MIN
 
    # Declare a -d array named “dp”
    # with size ‘N’ * ‘M’ * (‘K’ + 1).
    # Initialize the "dp" array with INT_MIN.
    dp = [[[INT_MIN for i in range(k + 1)] for j in range(m)] for l in range(n)]
 
    # Base case.
    dp[0][0][0] = 0
 
    # Iterate over the grid.
    for i in range(n):
        for j in range(m):
 
            # Iterate over the possible
            # values of ‘l’ in reverse order.
            for l in range(k - 1,-1,-1):
 
                # If the current state
                # of “dp” has positive value
                if (dp[i][j][l] >= 0):
 
                    # Update “dp” array for
                    #(‘l’ + 1)-th state since
                    # we include
                    # the current value
                    # of the grid.
                    dp[i][j][l + 1] = max(dp[i][j][l + 1],dp[i][j][l] + grid[i][j])
 
            # Again iterate over
            # all possible values of ‘l’.
            for l in range(k + 1):
 
                # If the current state
                # of “dp” has positive value
                if (dp[i][j][l] >= 0):
 
                    # Update the downward cell
                    # of the current cell
                    # if it exists.
                    if (i + 1 < n):
                        dp[i + 1][j][0] = max(dp[i + 1][j][0],dp[i][j][l])
 
                    # Update the right cell
                    # of the current cell
                    # if it exists.
                    if (j + 1 < m):
                        dp[i][j + 1][l] = max(dp[i][j + 1][l],dp[i][j][l])
 
    # Declare an integer variable “ans” and
    # initialize it with 0.
    ans = 0
 
    # Iterate over all possible values of l
    for l in range(k + 1):
 
        # Update ans as max of itself and
        # the dp value for (n -1, m - 1)th
        # cell  for the current value of l
        ans = max(ans, dp[n - 1][m - 1][l])
 
    # Return the “ans”.
    return ans
 
# Driver code
N, M, K = 3, 3, 2
mat = [ [ 2, 10, 8 ],[ 8, 8, 8 ],[ 0, 1, 0 ] ]
print(maximumProfits(N, M, K, mat))
 
# This code is contributed by shinjanpatra.


C#




// C# code to implement the approach
using System;
using System.Collections.Generic;
public class GFG{
 
  // Function to find the maximum path sum
  static int
    maximumProfits(int n, int m, int k,
                   List<List<int> > grid)
  {
 
    // Declare a -d array named “dp”
    // with size ‘N’ * ‘M’ * (‘K’ + 1).
    int[, ,] dp = new int[n,m,k + 1];
 
    // Initialize the "dp" array with INT_MIN.
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
        for (int l = 0; l < k + 1; l++) {
          dp[i, j, l] = Int32.MinValue;
        }
      }
    }
 
    // Base case.
    dp[0,0,0] = 0;
 
    // Iterate over the grid.
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
 
        // Iterate over the possible
        // values of ‘l’ in reverse order.
        for (int l = k - 1; l >= 0; l--) {
 
          // If the current state
          // of “dp” has positive value
          if (dp[i,j,l] >= 0) {
 
            // Update “dp” array for
            //(‘l’ + 1)-th state since
            // we include
            // the current value
            // of the grid.
            dp[i, j,l+1] = Math.Max(
              dp[i, j,l+1],
              dp[i, j,l]
              + grid[i][j]);
          }
        }
 
        // Again iterate over
        // all possible values of ‘l’.
        for (int l = 0; l < k + 1; l++) {
 
          // If the current state
          // of “dp” has positive value
          if (dp[i,j,l] >= 0) {
 
            // Update the downward cell
            // of the current cell
            // if it exists.
            if (i + 1 < n) {
              dp[i + 1,j,0]
                = Math.Max(dp[i + 1,j,0],
                           dp[i,j,l]);
            }
 
            // Update the right cell
            // of the current cell
            // if it exists.
            if (j + 1 < m) {
              dp[i,j + 1,l]
                = Math.Max(dp[i,j + 1,l],
                           dp[i,j, l]);
            }
          }
        }
      }
    }
 
    // Declare an integer variable “ans” and
    // initialize it with 0.
    int ans = 0;
 
    // Iterate over all possible values of l
    for (int l = 0; l < k + 1; l++) {
 
      // Update ans as max of itself and
      // the dp value for (n -1, m - 1)th
      // cell  for the current value of l
      ans = Math.Max(ans, dp[n - 1,m - 1,l]);
    }
 
    // Return the “ans”.
    return ans;
  }
 
  // Driver code
  static public void Main (){
 
    int N = 3, M = 3, K = 2;
    List<List<int>> mat = new List<List<int>>();
    mat.Add(new List<int> {2, 10, 8 });
    mat.Add(new List<int> { 8, 8, 8 });
    mat.Add(new List<int> { 0, 1, 0 });
 
    Console.Write(maximumProfits(N, M, K, mat));
  }
}
 
// This code is contributed by hrithikgarg03188.


Javascript




<script>
       // JavaScript code for the above approach
 
       // Function to find the maximum path sum
       function maximumProfits(n, m, k,
           grid) {
 
           // Declare a -d array named “dp”
           // with size ‘N’ * ‘M’ * (‘K’ + 1).
           let dp = new Array(n);
 
           for (let i = 0; i < dp.length; i++) {
               dp[i] = new Array(m)
               for (let j = 0; j < dp[i].length; j++) {
                   dp[i][j] = new Array(k + 1)
               }
           }
 
 
           // Initialize the "dp" array with INT_MIN.
           for (let i = 0; i < n; i++) {
               for (let j = 0; j < m; j++) {
                   for (let l = 0; l < k + 1; l++) {
                       dp[i][j][l] = Number.MIN_VALUE;
                   }
               }
           }
 
           // Base case.
           dp[0][0][0] = 0;
 
           // Iterate over the grid.
           for (let i = 0; i < n; i++) {
               for (let j = 0; j < m; j++) {
 
                   // Iterate over the possible
                   // values of ‘l’ in reverse order.
                   for (let l = k - 1; l >= 0; l--) {
 
                       // If the current state
                       // of “dp” has positive value
                       if (dp[i][j][l] >= 0) {
 
                           // Update “dp” array for
                           //(‘l’ + 1)-th state since
                           // we include
                           // the current value
                           // of the grid.
                           dp[i][j][l + 1]
                               = Math.max(dp[i][j][l + 1],
                                   dp[i][j][l]
                                   + grid[i][j]);
                       }
                   }
 
                   // Again iterate over
                   // all possible values of ‘l’.
                   for (let l = 0; l < k + 1; l++) {
 
                       // If the current state
                       // of “dp” has positive value
                       if (dp[i][j][l] >= 0) {
 
                           // Update the downward cell
                           // of the current cell
                           // if it exists.
                           if (i + 1 < n) {
                               dp[i + 1][j][0] = Math.max(
                                   dp[i + 1][j][0],
                                   dp[i][j][l]);
                           }
 
                           // Update the right cell
                           // of the current cell
                           // if it exists.
                           if (j + 1 < m) {
                               dp[i][j + 1][l] = Math.max(
                                   dp[i][j + 1][l],
                                   dp[i][j][l]);
                           }
                       }
                   }
               }
           }
 
           // Declare an integer variable “ans” and
           // initialize it with 0.
           let ans = 0;
 
           // Iterate over all possible values of l
           for (let l = 0; l < k + 1; l++) {
 
               // Update ans as max of itself and
               // the dp value for (n -1, m - 1)th
               // cell  for the current value of l
               ans = Math.max(ans, dp[n - 1][m - 1][l]);
           }
 
           // Return the “ans”.
           return ans;
       }
 
       // Driver code
 
       let N = 3, M = 3, K = 2;
       let mat = [[2, 10, 8],
       [8, 8, 8],
       [0, 1, 0]];
       document.write(maximumProfits(N, M, K, mat));
 
   // This code is contributed by Potta Lokesh
   </script>


Output

28

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


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 geeks!

Last Updated : 04 Apr, 2022
Like Article
Save Article
Previous
Next
Similar Reads
Complete Tutorials