Maximize sum by selecting M elements from the start or end of rows of a Matrix

Given a 2D array Blocks[][] consisting of N rows of variable length. The task is to select at most M elements with the maximum possible sum from Blocks[][] from either the start or end of a row.

Examples:

Input: N = 3, M = 4
Blocks[][] = {{2, 3, 5}, {-1, 7}, {8, 10}}
Output: 30
Explanation:
Select {5} from 1st row.
Select {7} from 2nd row.
Select {8, 10} from 3rd row.

Input: N = 3, M = 2
Blocks[][] = {{100, 3, -1}, {-1, 7, 10}, {8, 10, 15}}
Output: 115
Explanation:
select {100} from 1st row.
Skip 2nd row.
Select {15} from 3rd row.

Naive Approach: The simplest approach is to iterate through all the rows of the matrix and push all the elements into a vector and sort it. Calculate the sum of the last M elements and print it as the required answer.

Time Complexity: O(N * KlogK), where K is the maximum size any block can have.
Auxiliary Space: O(N * K)

Efficient Approach: To optimize the above approach, the idea is to use Dynamic Programming using Memoization. Follow the steps below:

• Given N rows and from each row, select any segment from the ith row, say from l to r.
• The count of elements in ith row is (r – l + 1) and proceed to the next row.
• To calculate the maximum sum, use the prefix sum technique in order to calculate the sum.
• Initialize a 2D array dp[][], where dp[N][M] stores the maximum sum by selecting at most M elements from N rows.
• Consider the following two scenarios:
• Either skip the current row.
• Select any segment from the current row that does not exceed the number of elements selected.

Below is the implementation of the above approach:

C++14

 `// C++ program for the above approach` `#include ` `using` `namespace` `std;`   `// Funtion to selct m elements` `// having maximum sum` `long` `mElementsWithMaxSum(vector > matrix,` `                         ``int` `M, ``int` `block,` `                         ``vector > dp)` `{` `    `  `    ``// Base case` `    ``if` `(block == matrix.size())` `        ``return` `0;`   `    ``// If precomputed subproblem occurred` `    ``if` `(dp[block][M] != -1)` `        ``return` `dp[block][M];`   `    ``// Either skip the current row` `    ``long` `ans = mElementsWithMaxSum(matrix, M,` `                                   ``block + 1, dp);`   `    ``// Iterate through all the possible` `    ``// segments of current row` `    ``for``(``int` `i = 0;` `            ``i < matrix[block].size(); i++)` `    ``{` `        ``for``(``int` `j = i;` `                ``j < matrix[block].size(); j++)` `        ``{`   `            ``// Check if it is possible to select` `            ``// elements from i to j` `            ``if` `(j - i + 1 <= M)` `            ``{` `                `  `                ``// Compuete the sum of i to j as` `                ``// calculated` `                ``ans = max(ans, matrix[block][j] - ` `                         ``((i - 1) >= 0 ? ` `                         ``matrix[block][i - 1] : 0) + ` `                         ``mElementsWithMaxSum(matrix,` `                                             ``M - j +` `                                             ``i - 1,` `                                         ``block + 1, dp));` `            ``}` `        ``}` `    ``}`   `    ``// Store the computed answer and return` `    ``return` `dp[block][M] = ans;` `}`   `// Function to precompute the prefix sum` `// for every row of the matrix` `void` `preComputing(vector> matrix,` `                  ``int` `N)` `{` `    `  `    ``// Preprocessing to calculate sum from i to j` `    ``for``(``int` `i = 0; i < N; i++) ` `    ``{` `        ``for``(``int` `j = 0; j < matrix[i].size(); j++) ` `        ``{` `            ``matrix[i][j] = (j > 0 ? ` `                  ``matrix[i][j - 1] : 0) +` `                  ``matrix[i][j];` `        ``}` `    ``}` `}`   `// Utility function to selct m elements having` `// maximum sum` `void` `mElementsWithMaxSumUtil(vector> matrix,` `                             ``int` `M, ``int` `N)` `{` `    `  `    ``// Preprocessing step` `    ``preComputing(matrix, N);` `    ``long` `sum = 10;` `    `  `    ``// Initialize dp array with -1` `    ``vector> dp;` `    ``dp.resize(N + 5);` `    ``for``(``int` `i = 0; i < N + 5; i++)` `        ``for``(``int` `j = 0; j < M + 5; j++)` `            ``dp[i].push_back(-1);`   `    ``// Stores maximum sum of M elements` `     ``sum += mElementsWithMaxSum(matrix, M,` `                                ``0, dp);` `    `  `    ``cout << sum;` `}`   `// Driver Code` `int` `main()` `{` `    `  `    ``// Given N` `    ``int` `N = 3;`   `    ``// Given M` `    ``int` `M = 4;`   `    ``// Given matrix` `    ``vector> matrix = { { 2, 3, 5 }, ` `                                   ``{ -1, 7 }, ` `                                   ``{ 8, 10 } };`   `    ``// Function call` `    ``mElementsWithMaxSumUtil(matrix, M, N);` `}`   `// This code is contributed by grand_master`

Java

 `// Java program for the above approach`   `import` `java.util.*;` `public` `class` `GFG {`   `    ``// Funtion to selct m elements` `    ``// having maximum sum` `    ``public` `static` `long` `    ``mElementsWithMaxSum(``long``[][] matrix,` `                        ``int` `M, ``int` `block,` `                        ``long``[][] dp)` `    ``{` `        ``// Base case` `        ``if` `(block == matrix.length)` `            ``return` `0``;`   `        ``// If precomputed subproblem occurred` `        ``if` `(dp[block][M] != -``1``)` `            ``return` `dp[block][M];`   `        ``// Either skip the current row` `        ``long` `ans` `            ``= mElementsWithMaxSum(matrix, M,` `                                ``block + ``1``, dp);`   `        ``// Iterate through all the possible` `        ``// segments of current row` `        ``for` `(``int` `i = ``0``; ` `            ``i < matrix[block].length; i++) {` `            ``for` `(``int` `j = i; ` `                ``j < matrix[block].length; j++) {`   `                ``// Check if it is possible to select` `                ``// elements from i to j` `                ``if` `(j - i + ``1` `<= M) {`   `                    ``// Compuete the sum of i to j as` `                    ``// calculated` `                    ``ans = Math.max(` `                        ``ans,` `                        ``matrix[block][j]` `                            ``- ((i - ``1``) >= ``0` `                            ``? matrix[block][i - ``1``]` `                            ``: ``0``)` `                            ``+ mElementsWithMaxSum(` `                                ``matrix, M - j + i - ``1``,` `                                ``block + ``1``, dp));` `                ``}` `            ``}` `        ``}`   `        ``// Store the computed answer and return` `        ``return` `dp[block][M] = ans;` `    ``}`   `    ``// Function to precompute the prefix sum` `    ``// for every row of the matrix` `    ``public` `static` `void` `    ``preComputing(``long``[][] matrix, ``int` `N)` `    ``{` `        ``// Preprocessing to calculate sum from i to j` `        ``for` `(``int` `i = ``0``; ` `            ``i < N; i++) {` `            ``for` `(``int` `j = ``0``; ` `                ``j < matrix[i].length; j++) {` `                ``matrix[i][j]` `                    ``= (j > ``0` `                    ``? matrix[i][j - ``1``] : ``0``)` `                    ``+ matrix[i][j];` `            ``}` `        ``}` `    ``}`   `    ``// Utility function to selct m elements having` `    ``// maximum sum` `    ``public` `static` `void` `    ``mElementsWithMaxSumUtil(``long``[][] matrix,` `                            ``int` `M, ``int` `N)` `    ``{` `        ``// Preprocessing step` `        ``preComputing(matrix, N);`   `        ``// Initialize dp array with -1` `        ``long` `dp[][] = ``new` `long``[N + ``5``][M + ``5``];` `        ``for` `(``long` `i[] : dp)` `            ``Arrays.fill(i, -``1``);`   `        ``// Stores maximum sum of M elements` `        ``long` `sum = mElementsWithMaxSum(matrix, M,` `                                    ``0``, dp);`   `        ``// Print the sum` `        ``System.out.print(sum);` `    ``}`   `    ``// Driver Code` `    ``public` `static` `void` `main(String args[])` `    ``{` `        ``// Given N` `        ``int` `N = ``3``;`   `        ``// Given M` `        ``int` `M = ``4``;`   `        ``// Given matrix` `        ``long``[][] matrix` `            ``= { { ``2``, ``3``, ``5` `}, { -``1``, ``7` `},` `                ``{ ``8``, ``10` `} };`   `        ``// Function Call` `        ``mElementsWithMaxSumUtil(matrix, M, N);` `    ``}` `}`

Python3

 `# Python3 program for the above approach`   `# Funtion to selct m elements` `# having maximum sum` `def` `mElementsWithMaxSum(matrix, M, block, dp):` `    `  `    ``# Base case` `    ``if` `block ``=``=` `len``(matrix):` `        ``return` `0`   `    ``# If precomputed subproblem occurred` `    ``if` `(dp[block][M] !``=` `-``1``):` `        ``return` `dp[block][M]`   `    ``# Either skip the current row` `    ``ans ``=` `mElementsWithMaxSum(matrix, M, ` `                              ``block ``+` `1``, dp)`   `    ``# Iterate through all the possible` `    ``# segments of current row` `    ``for` `i ``in` `range``(``len``(matrix[block])):` `        ``for` `j ``in` `range``(i, ``len``(matrix[block])):` `            `  `            ``# Check if it is possible to select` `            ``# elements from i to j` `            ``if` `(j ``-` `i ``+` `1` `<``=` `M):` `                `  `                ``# Compuete the sum of i to j as` `                ``# calculated` `                ``x ``=` `0` `                ``if` `i ``-` `1` `>``=` `0``:` `                    ``x ``=` `matrix[block][i ``-` `1``]` `                    `  `                ``ans ``=` `max``(ans, matrix[block][j] ``-` `x ``+` `                               ``mElementsWithMaxSum(matrix,` `                                                   ``M ``-` `j ``+` `                                                   ``i ``-` `1``, ` `                                               ``block ``+` `1``, dp))`   `    ``# Store the computed answer and return` `    ``dp[block][M] ``=` `ans` `    `  `    ``return` `ans`   `# Function to precompute the prefix sum` `# for every row of the matrix` `def` `preComputing(matrix, N):` `    `  `    ``# Preprocessing to calculate sum from i to j` `    ``for` `i ``in` `range``(N):` `        ``for` `j ``in` `range``(``len``(matrix[i])):` `            ``if` `j > ``0``:` `                ``matrix[i][j] ``=` `matrix[i][j ``-` `1``]` `                `  `    ``return` `matrix`   `# Utility function to selct m elements having` `# maximum sum` `def` `mElementsWithMaxSumUtil(matrix, M, N):` `    `  `    ``# Preprocessing step` `    ``matrix ``=` `preComputing(matrix, N)` `    ``sum` `=` `20`   `    ``# Initialize dp array with -1` `    ``dp ``=` `[[``-``1` `for` `i ``in` `range``(M ``+` `5``)]` `              ``for` `i ``in` `range``(N ``+` `5``)]`   `    ``# Stores maximum sum of M elements` `    ``sum` `+``=` `mElementsWithMaxSum(matrix, M, ``0``, dp)`   `    ``print``(``sum``)`   `# Driver Code` `if` `__name__ ``=``=` `'__main__'``:` `    `  `    ``# Given N` `    ``N ``=` `3`   `    ``# Given M` `    ``M ``=` `4`   `    ``# Given matrix` `    ``matrix ``=` `[ [ ``2``, ``3``, ``5` `],` `               ``[ ``-``1``, ``7` `],` `               ``[ ``8``, ``10` `] ]`   `    ``# Function call` `    ``mElementsWithMaxSumUtil(matrix, M, N)`   `# This code is contributed by mohit kumar 29`

C#

 `// C# program for ` `// the above approach` `using` `System;` `class` `GFG{`   `// Funtion to selct m elements` `// having maximum sum` `public` `static` `int` `mElementsWithMaxSum(``int``[,] matrix,` `                                    ``int` `M, ``int` `block,` `                                    ``int``[,] dp)` `{` `// Base case` `if` `(block == matrix.GetLength(0))` `    ``return` `0;`   `// If precomputed subproblem occurred` `if` `(dp[block, M] != -1)` `    ``return` `dp[block, M];`   `// Either skip the current row` `int` `ans = mElementsWithMaxSum(matrix, M,` `                                ``block + 1, dp);`   `// Iterate through all the possible` `// segments of current row` `for` `(``int` `i = 0; ` `        ``i < GetRow(matrix, block).Length; i++) ` `{` `    ``for` `(``int` `j = i; ` `            ``j < GetRow(matrix, block).Length; j++) ` `    ``{` `    ``// Check if it is possible to select` `    ``// elements from i to j` `    ``if` `(j - i + 1 <= M) ` `    ``{` `        ``// Compuete the sum of i to j as` `        ``// calculated` `        ``ans = Math.Max(ans, matrix[block, j] - ` `                                ``((i - 1) >= 0 ? ` `                            ``matrix[block, i - 1] : 0) + ` `                            ``mElementsWithMaxSum(matrix, ` `                                                ``M - j + i - 1,` `                                                ``block + 1, dp));` `    ``}` `    ``}` `}`   `// Store the computed answer and return` `return` `dp[block, M] = ans;` `}`   `// Function to precompute the prefix sum` `// for every row of the matrix` `public` `static` `void` `preComputing(``int``[,] matrix, ` `                                ``int` `N)` `{` `// Preprocessing to calculate sum from i to j` `for` `(``int` `i = 0; i < N; i++) ` `{` `    ``for` `(``int` `j = 0; ` `            ``j < GetRow(matrix, i).Length; j++) ` `    ``{` `    ``matrix[i, j] = (j > 0 ? matrix[i, j - 1] : 0) + ` `                            ``matrix[i, j];` `    ``}` `}` `}`   `// Utility function to selct ` `// m elements having maximum sum` `public` `static` `void` `mElementsWithMaxSumUtil(``int``[,] matrix,` `                                        ``int` `M, ``int` `N)` `{` `// Preprocessing step` `preComputing(matrix, N);`   `// Initialize dp array with -1` `int` `[,]dp = ``new` `int``[N + 5, M + 5];` `for``(``int` `i = 0; i < N + 5; i++)` `{` `    ``for` `(``int` `j = 0; j < M + 5; j++) ` `    ``{` `    ``dp[i, j] = -1;` `    ``}` `}`   `// Stores maximum sum of M elements` `int` `sum = mElementsWithMaxSum(matrix, M,` `                                ``0, dp);`   `// Print the sum` `Console.Write(sum);` `}`   `public` `static` `int``[] GetRow(``int``[,] matrix, ` `                        ``int` `row)` `{` `var` `rowLength = matrix.GetLength(1);` `var` `rowVector = ``new` `int``[rowLength];`   `for` `(``var` `i = 0; i < rowLength; i++)` `    ``rowVector[i] = matrix[row, i];`   `return` `rowVector;` `}`   `// Driver Code` `public` `static` `void` `Main(String []args)` `{` `// Given N` `int` `N = 3;`   `// Given M` `int` `M = 4;`   `// Given matrix` `int``[,] matrix = {{2, 3, 5}, ` `                ``{-1, 7,0},` `                ``{8, 10, 0}};`   `// Function Call` `mElementsWithMaxSumUtil(matrix, M, N);` `}` `}`   `// This code is contributed by Princi Singh`

Output:

```30

```

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

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.

My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.