Maximize sum of topmost elements of S stacks by popping at most N elements
Last Updated :
10 Aug, 2023
Given S stacks of length M, the task is to maximize the sum of elements at the top of each stack by popping at most N elements.
Example:
Input: S = 1, N = 3, stacks = { 5, 1, 2, 8, 9 }
Output: 8
Explanation:
Maximum 3 elements can be removed.
The current element at the top of the stack is 5.
On removal of 5, the new element at the top is 1.
On removal of 1, the new element at the top is 2.
On removal of 2, the new element at the top is 8.
No further pop operation is allowed.
Hence, the maximum possible value at the top of the stack is 8.
Input: S = 2, N = 2, stacks = { { 2, 6, 4, 5}, {1, 6, 15, 10} }
Output: 17
Explanation:
Current sum of the elements at the top = 2 + 1 = 3.
Popping 1 from top of the second stack only makes the sum 8 (5 + 2 = 8)
Popping 2 from the top of the second stack only makes the sum 7 (6 + 1).
Popping both 1 and 2 from the top of each stack makes the sum 12 (6 + 6).
Popping 2 and 6 from the first stack makes the sum 5 (4 + 1).
Popping 1 and 6 from the second stack leaves 15 as the element at the top.
Hence, the sum of elements at the top of the two stacks is maximized (15 + 2 = 17).
Approach: This problem can be reduced to a 0/1 Knapsack problem. To solve the problem, follow the steps below:
- Create a 2D table dp[][] with (S + 1) rows and (N + 1) columns. At every index dp[i][j], store the maximum sum possible by popping j elements up to the ith stack.
- Initialize all indices dp[][] by 0.
- Iterate over each stack from i = 0 to S – 1
- Now, for every ith stack, calculate the maximum possible sum by popping j (1 to N) elements..
- These j elements can be selected from all the i stacks already visited. Hence, dp[i+1][j] stores the maximum of stacks[i][k] + dp[i][j – k] for all values of k ranging from 0 to min(j, size of stack). The relation stacks[i][k] + dp[i][j-k] denotes the sum obtained by popping k elements from the current ith stack and maximum sum possible by popping j – k elements from the already visited stacks.
- Once, done for all i stacks, find the maximum of dp[S][i] for all i in range [1, N – 1].
- The maximum value obtained at the previous step is the required answer.
Below code is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int maximumSum( int S, int M, int N,
vector<vector< int > >& stacks)
{
int dp[S + 1][N + 1];
memset (dp, INT_MIN, sizeof (dp));
for ( int i = 0; i < S; i++) {
for ( int j = 0; j <= N; j++) {
for ( int k = 0; k <= min(j, M); k++) {
dp[i + 1][j]
= max(dp[i + 1][j],
stacks[i][k]
+ dp[i][j - k]);
}
}
}
int result = INT_MIN;
for ( int i = 0; i <= N; i++) {
result = max(result, dp[S][i]);
}
return result;
}
int main()
{
int S = 2;
int M = 4;
vector<vector< int > > stacks = {
{ 2, 6, 4, 5 },
{ 1, 6, 15, 10 }
};
int N = 3;
cout << maximumSum(S, M, N, stacks);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int maximumSum( int S, int M, int N,
int [][]stacks)
{
int [][]dp = new int [S + 1 ][N + 1 ];
for ( int i = 0 ; i < S; i++)
{
for ( int j = 0 ; j <= N; j++)
{
for ( int k = 0 ; k <= Math.min(j, M); k++)
{
dp[i + 1 ][j] = Math.max(dp[i + 1 ][j],
stacks[i][k] +
dp[i][j - k]);
}
}
}
int result = Integer.MIN_VALUE;
for ( int i = 0 ; i <= N; i++)
{
result = Math.max(result, dp[S][i]);
}
return result;
}
public static void main(String[] args)
{
int S = 2 ;
int M = 4 ;
int [][]stacks = {{ 2 , 6 , 4 , 5 },
{ 1 , 6 , 15 , 10 }};
int N = 3 ;
System.out.print(maximumSum(S, M, N, stacks));
}
}
|
Python3
import sys
def maximumSum(S, M, N, stacks):
dp = [[ 0 for x in range (N + 1 )]
for y in range (S + 1 )]
for i in range (S):
for j in range (N + 1 ):
for k in range ( min (j, M) + 1 ):
dp[i + 1 ][j] = max (dp[i + 1 ][j],
stacks[i][k] +
dp[i][j - k])
result = - sys.maxsize - 1
for i in range (N + 1 ):
result = max (result, dp[S][i])
return result
if __name__ = = "__main__" :
S = 2
M = 4
stacks = [ [ 2 , 6 , 4 , 5 ],
[ 1 , 6 , 15 , 10 ] ]
N = 3
print (maximumSum(S, M, N, stacks))
|
C#
using System;
class GFG{
static int maximumSum( int S, int M, int N,
int [,]stacks)
{
int [,]dp = new int [S + 1, N + 1];
for ( int i = 0; i < S; i++)
{
for ( int j = 0; j <= N; j++)
{
for ( int k = 0;
k <= Math.Min(j, M); k++)
{
dp[i + 1, j] = Math.Max(dp[i + 1, j],
stacks[i, k] +
dp[i, j - k]);
}
}
}
int result = int .MinValue;
for ( int i = 0; i <= N; i++)
{
result = Math.Max(result, dp[S, i]);
}
return result;
}
public static void Main(String[] args)
{
int S = 2;
int M = 4;
int [,]stacks = { { 2, 6, 4, 5 },
{ 1, 6, 15, 10 } };
int N = 3;
Console.Write(maximumSum(S, M, N, stacks));
}
}
|
Javascript
<script>
function maximumSum(S, M, N, stacks)
{
var dp = Array.from(Array(S+1), ()=> Array(N+1).fill(0));
for ( var i = 0; i < S; i++) {
for ( var j = 0; j <= N; j++) {
for ( var k = 0; k <= Math.min(j, M); k++) {
dp[i + 1][j]
= Math.max(dp[i + 1][j],
stacks[i][k]
+ dp[i][j - k]);
}
}
}
var result = -1000000000;
for ( var i = 0; i <= N; i++) {
result = Math.max(result, dp[S][i]);
}
return result;
}
var S = 2;
var M = 4;
var stacks = [
[ 2, 6, 4, 5 ],
[ 1, 6, 15, 10 ]
];
var N = 3;
document.write( maximumSum(S, M, N, stacks));
</script>
|
Time complexity: O( S*(M + N * (min(N, M))
Auxiliary Space: O(S*N), for dp array
Efficient approach : Space optimization
In previous approach the current value dp[i][j] is only depend upon the current and previous row values of DP. So to optimize the space complexity we use a single 1D array to store the computations.
Implementation steps:
- Create a 1D vector dp of size N+1.
- Set a base case by initializing the values of DP .
- Now iterate over subproblems by the help of nested loop and get the current value from previous computations.
- Now Create a temporary 1d vector new_dp used to store the current values from previous computations.
- After every iteration assign the value of new_dp to dp for further iteration.
- At last return and print the final answer stored in dp[N].
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
int maximumSum( int S, int M, int N,
vector<vector< int > >& stacks)
{
vector< int > dp(N + 1, INT_MIN);
dp[0] = 0;
for ( int i = 0; i < S; i++) {
vector< int > new_dp(N + 1, INT_MIN);
for ( int j = 0; j <= N; j++) {
for ( int k = 0; k <= min(j, M); k++) {
new_dp[j] = max(new_dp[j], stacks[i][k] + dp[j - k]);
}
}
dp = new_dp;
}
return dp[N];
}
int main()
{
int S = 2;
int M = 4;
vector<vector< int > > stacks = {
{ 2, 6, 4, 5 },
{ 1, 6, 15, 10 }
};
int N = 3;
cout << maximumSum(S, M, N, stacks);
return 0;
}
|
Java
import java.util.*;
public class Main {
static int maximumSum( int S, int M, int N,
List<List<Integer> > stacks)
{
List<Integer> dp = new ArrayList<>(
Collections.nCopies(N + 1 , Integer.MIN_VALUE));
dp.set( 0 , 0 );
for ( int i = 0 ; i < S; i++) {
List<Integer> new_dp
= new ArrayList<>(Collections.nCopies(
N + 1 , Integer.MIN_VALUE));
for ( int j = 0 ; j <= N; j++) {
for ( int k = 0 ; k <= Math.min(j, M); k++) {
new_dp.set(
j, Math.max(new_dp.get(j),
stacks.get(i).get(k)
+ dp.get(j - k)));
}
}
dp = new_dp;
}
return dp.get(N);
}
public static void main(String[] args)
{
int S = 2 ;
int M = 4 ;
List<List<Integer> > stacks = new ArrayList<>();
stacks.add(Arrays.asList( 2 , 6 , 4 , 5 ));
stacks.add(Arrays.asList( 1 , 6 , 15 , 10 ));
int N = 3 ;
System.out.println(maximumSum(S, M, N, stacks));
}
}
|
Python3
from typing import List
def maximumSum(S: int , M: int , N: int ,
stacks: List [ List [ int ]]) - > int :
dp = [ float ( '-inf' )] * (N + 1 )
dp[ 0 ] = 0
for i in range (S):
new_dp = [ float ( '-inf' )] * (N + 1 )
for j in range (N + 1 ):
for k in range ( min (j, M) + 1 ):
new_dp[j] = max (new_dp[j], stacks[i][k] + dp[j - k])
dp = new_dp
return dp[N]
if __name__ = = '__main__' :
S = 2
M = 4
stacks = [
[ 2 , 6 , 4 , 5 ],
[ 1 , 6 , 15 , 10 ]
]
N = 3
print (maximumSum(S, M, N, stacks))
|
C#
using System;
using System.Collections.Generic;
public class GFG
{
static int MaximumSum( int S, int M, int N, List<List< int >> stacks)
{
List< int > dp = new List< int >( new int [N + 1]);
dp[0] = 0;
for ( int i = 0; i < S; i++)
{
List< int > new_dp = new List< int >( new int [N + 1]);
for ( int j = 0; j <= N; j++)
{
for ( int k = 0; k <= Math.Min(j, M); k++)
{
new_dp[j] = Math.Max(new_dp[j], stacks[i][k] + dp[j - k]);
}
}
dp = new_dp;
}
return dp[N];
}
public static void Main( string [] args)
{
int S = 2;
int M = 4;
List<List< int >> stacks = new List<List< int >>();
stacks.Add( new List< int > { 2, 6, 4, 5 });
stacks.Add( new List< int > { 1, 6, 15, 10 });
int N = 3;
Console.WriteLine(MaximumSum(S, M, N, stacks));
}
}
|
Javascript
function maximumSum(S, M, N, stacks) {
let dp = new Array(N + 1).fill(Number.MIN_SAFE_INTEGER);
dp[0] = 0;
for (let i = 0; i < S; i++) {
let new_dp = new Array(N + 1).fill(Number.MIN_SAFE_INTEGER);
for (let j = 0; j <= N; j++) {
for (let k = 0; k <= Math.min(j, M); k++) {
new_dp[j] = Math.max(new_dp[j], stacks[i][k] + dp[j - k]);
}
}
dp = new_dp;
}
return dp[N];
}
let S = 2;
let M = 4;
let stacks = [
[2, 6, 4, 5],
[1, 6, 15, 10]
];
let N = 3;
console.log(maximumSum(S, M, N, stacks));
|
Output:
21
Time complexity: O( S*(M + N * (min(N, M))
Auxiliary Space: O(N)
Share your thoughts in the comments
Please Login to comment...