Open In App

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

Improve
Improve
Like Article
Like
Save
Share
Report

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)



Last Updated : 04 Apr, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads