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.
- Iterate over all the possible values of l in reverse order (from K-1 to 0):
- 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++ 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 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 |
# 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# 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. |
<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>
|
28
Time Complexity: O (N * M * K)
Auxiliary Space: O (N * M * K)