Open In App

Maximize sum of topmost elements of S stacks by popping at most N elements

Improve
Improve
Like Article
Like
Save
Share
Report

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:
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: 
 

  1. 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.
  2. Initialize all indices dp[][] by 0.
  3. Iterate over each stack from i = 0 to S – 1
  4. Now, for every ith stack, calculate the maximum possible sum by popping j (1 to N) elements..
  5. 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.
  6. Once, done for all i stacks, find the maximum of dp[S][i] for all i in range [1, N – 1].
  7. The maximum value obtained at the previous step is the required answer.

Below code is the implementation of the above approach:
 

C++




// C++ Program to maximize the
// sum of top of the stack
// values of S stacks by popping
// at most N elements
 
#include <bits/stdc++.h>
using namespace std;
 
// Function for computing the
// maximum sum at the top of
// the stacks after popping at
// most N elements from S stack
int maximumSum(int S, int M, int N,
            vector<vector<int> >& stacks)
{
    // Constructing a dp matrix
    // of dimensions (S+1) x (N+1)
    int dp[S + 1][N + 1];
 
    // Initialize all states
    memset(dp, INT_MIN, sizeof(dp));
 
    // Loop over all i stacks
    for (int i = 0; i < S; i++) {
        for (int j = 0; j <= N; j++) {
            for (int k = 0; k <= min(j, M); k++) {
 
                // Store the maximum of
                // popping j elements
                // up to the current stack
                // by popping k elements
                // from current stack and
                // j - k elements from all
                // previous stacks combined
                dp[i + 1][j]
                    = max(dp[i + 1][j],
                        stacks[i][k]
                            + dp[i][j - k]);
            }
        }
    }
 
    // Store the maximum sum of
    // popping N elements across
    // all stacks
    int result = INT_MIN;
    for (int i = 0; i <= N; i++) {
        result = max(result, dp[S][i]);
    }
 
    // dp[S][N] has the maximum sum
    return result;
}
 
// Driver Program
int main()
{
    // Number of stacks
    int S = 2;
    // Length of each stack
    int M = 4;
 
    vector<vector<int> > stacks = {
        { 2, 6, 4, 5 },
        { 1, 6, 15, 10 }
    };
 
    // Maximum elements that
    // can be popped
    int N = 3;
 
    cout << maximumSum(S, M, N, stacks);
 
    return 0;
}


Java




// Java Program to maximize the
// sum of top of the stack
// values of S stacks by popping
// at most N elements
import java.util.*;
class GFG{
 
// Function for computing the
// maximum sum at the top of
// the stacks after popping at
// most N elements from S stack
static int maximumSum(int S, int M, int N,
                      int [][]stacks)
{
    // Constructing a dp matrix
    // of dimensions (S+1) x (N+1)
    int [][]dp = new int[S + 1][N + 1];
 
    // Loop over all i stacks
    for (int i = 0; i < S; i++)
    {
        for (int j = 0; j <= N; j++)
        {
            for (int k = 0; k <= Math.min(j, M); k++)
            {
 
                // Store the maximum of
                // popping j elements
                // up to the current stack
                // by popping k elements
                // from current stack and
                // j - k elements from all
                // previous stacks combined
                dp[i + 1][j] = Math.max(dp[i + 1][j],
                                        stacks[i][k] +
                                        dp[i][j - k]);
            }
        }
    }
 
    // Store the maximum sum of
    // popping N elements across
    // all stacks
    int result = Integer.MIN_VALUE;
    for (int i = 0; i <= N; i++)
    {
        result = Math.max(result, dp[S][i]);
    }
 
    // dp[S][N] has the maximum sum
    return result;
}
 
// Driver Program
public static void main(String[] args)
{
    // Number of stacks
    int S = 2;
     
    // Length of each stack
    int M = 4;
 
    int [][]stacks = {{ 2, 6, 4, 5 },
                      { 1, 6, 15, 10 }};
 
    // Maximum elements that
    // can be popped
    int N = 3;
 
    System.out.print(maximumSum(S, M, N, stacks));
}
}
 
// This code is contributed by 29AjayKumar


Python3




# Python3 program to maximize the
# sum of top of the stack values
# of S stacks by popping at most
# N element
import sys
 
# Function for computing the
# maximum sum at the top of
# the stacks after popping at
# most N elements from S stack
def maximumSum(S, M, N, stacks):
 
    # Constructing a dp matrix
    # of dimensions (S+1) x (N+1)
    dp = [[0 for x in range(N + 1)]
             for y in range(S + 1)]
 
    # Loop over all i stacks
    for i in range(S):
        for j in range(N + 1):
            for k in range(min(j, M) + 1):
                 
                # Store the maximum of
                # popping j elements
                # up to the current stack
                # by popping k elements
                # from current stack and
                # j - k elements from all
                # previous stacks combined
                dp[i + 1][j] = max(dp[i + 1][j],
                                   stacks[i][k] +
                                   dp[i][j - k])
 
    # Store the maximum sum of
    # popping N elements across
    # all stacks
    result = -sys.maxsize - 1
    for i in range(N + 1):
        result = max(result, dp[S][i])
 
    # dp[S][N] has the maximum sum
    return result
 
# Driver code
if __name__ == "__main__":
 
    # Number of stacks
    S = 2
     
    # Length of each stack
    M = 4
  
    stacks = [ [ 2, 6, 4, 5 ],
               [ 1, 6, 15, 10 ] ]
 
    # Maximum elements that
    # can be popped
    N = 3
 
    print(maximumSum(S, M, N, stacks))
 
# This code is contributed by chitranayal


C#




// C# program to maximize the sum
// of top of the stack values of
// S stacks by popping at most N
// elements
using System;
 
class GFG{
 
// Function for computing the
// maximum sum at the top of
// the stacks after popping at
// most N elements from S stack
static int maximumSum(int S, int M, int N,
                      int [,]stacks)
{
     
    // Constructing a dp matrix
    // of dimensions (S+1) x (N+1)
    int [,]dp = new int[S + 1, N + 1];
 
    // Loop over all i stacks
    for(int i = 0; i < S; i++)
    {
        for(int j = 0; j <= N; j++)
        {
            for(int k = 0;
                    k <= Math.Min(j, M); k++)
            {
                 
                // Store the maximum of popping
                // j elements up to the current
                // stack by popping k elements
                // from current stack and
                // j - k elements from all
                // previous stacks combined
                dp[i + 1, j] = Math.Max(dp[i + 1, j],
                                        stacks[i, k] +
                                        dp[i, j - k]);
            }
        }
    }
 
    // Store the maximum sum of
    // popping N elements across
    // all stacks
    int result = int.MinValue;
    for(int i = 0; i <= N; i++)
    {
        result = Math.Max(result, dp[S, i]);
    }
 
    // dp[S,N] has the maximum sum
    return result;
}
 
// Driver code
public static void Main(String[] args)
{
     
    // Number of stacks
    int S = 2;
     
    // Length of each stack
    int M = 4;
 
    int [,]stacks = { { 2, 6, 4, 5 },
                      { 1, 6, 15, 10 } };
 
    // Maximum elements that
    // can be popped
    int N = 3;
 
    Console.Write(maximumSum(S, M, N, stacks));
}
}
 
// This code is contributed by 29AjayKumar


Javascript




<script>
 
// Javascript Program to maximize the
// sum of top of the stack
// values of S stacks by popping
// at most N elements
 
// Function for computing the
// maximum sum at the top of
// the stacks after popping at
// most N elements from S stack
function maximumSum(S, M, N, stacks)
{
    // Constructing a dp matrix
    // of dimensions (S+1) x (N+1)
    var dp = Array.from(Array(S+1), ()=> Array(N+1).fill(0));
 
    // Loop over all i stacks
    for (var i = 0; i < S; i++) {
        for (var j = 0; j <= N; j++) {
            for (var k = 0; k <= Math.min(j, M); k++) {
 
                // Store the maximum of
                // popping j elements
                // up to the current stack
                // by popping k elements
                // from current stack and
                // j - k elements from all
                // previous stacks combined
                dp[i + 1][j]
                    = Math.max(dp[i + 1][j],
                        stacks[i][k]
                            + dp[i][j - k]);
            }
        }
    }
 
    // Store the maximum sum of
    // popping N elements across
    // all stacks
    var result = -1000000000;
    for (var i = 0; i <= N; i++) {
        result = Math.max(result, dp[S][i]);
    }
 
    // dp[S][N] has the maximum sum
    return result;
}
 
// Driver Program
// Number of stacks
var S = 2;
// Length of each stack
var M = 4;
var stacks = [
    [ 2, 6, 4, 5 ],
    [ 1, 6, 15, 10 ]
    ];
// Maximum elements that
// can be popped
var N = 3;
document.write( maximumSum(S, M, N, stacks));
 
</script>


Output

21

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;
 
// Function for computing the
// maximum sum at the top of
// the stacks after popping at
// most N elements from S stack
int maximumSum(int S, int M, int N,
        vector<vector<int> >& stacks)
{
    // Constructing a dp vector of size N+1
    vector<int> dp(N + 1, INT_MIN);
 
    // Initialize the 0th index
    dp[0] = 0;
 
    // Loop over all i stacks
    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++) {
 
                // Store the maximum of
                // popping j elements
                // up to the current stack
                // by popping k elements
                // from current stack and
                // j - k elements from all
                // previous stacks combined
                new_dp[j] = max(new_dp[j], stacks[i][k] + dp[j - k]);
            }
        }
        dp = new_dp;
    }
 
    // dp[N] has the maximum sum
    return dp[N];
}
 
// Driver Program
int main()
{
    // Number of stacks
    int S = 2;
    // Length of each stack
    int M = 4;
 
    vector<vector<int> > stacks = {
        { 2, 6, 4, 5 },
        { 1, 6, 15, 10 }
    };
 
    // Maximum elements that
    // can be popped
    int N = 3;
 
    cout << maximumSum(S, M, N, stacks);
 
    return 0;
}
// --- by bhardwajji


Java




import java.util.*;
 
public class Main {
    static int maximumSum(int S, int M, int N,
                          List<List<Integer> > stacks)
    {
        // Constructing a dp vector of size N+1
        List<Integer> dp = new ArrayList<>(
            Collections.nCopies(N + 1, Integer.MIN_VALUE));
 
        // Initialize the 0th index
        dp.set(0, 0);
 
        // Loop over all i stacks
        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++) {
 
                    // Store the maximum of
                    // popping j elements
                    // up to the current stack
                    // by popping k elements
                    // from current stack and
                    // j - k elements from all
                    // previous stacks combined
                    new_dp.set(
                        j, Math.max(new_dp.get(j),
                                    stacks.get(i).get(k)
                                        + dp.get(j - k)));
                }
            }
            dp = new_dp;
        }
 
        // dp[N] has the maximum sum
        return dp.get(N);
    }
 
    public static void main(String[] args)
    {
        // Number of stacks
        int S = 2;
        // Length of each stack
        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));
 
        // Maximum elements that can be popped
        int N = 3;
 
        System.out.println(maximumSum(S, M, N, stacks));
    }
}


Python3




from typing import List
 
# Function for computing the
# maximum sum at the top of
# the stacks after popping at
# most N elements from S stack
def maximumSum(S: int, M: int, N: int,
               stacks: List[List[int]]) -> int:
    # Constructing a dp vector of size N+1
    dp = [float('-inf')] * (N + 1)
 
    # Initialize the 0th index
    dp[0] = 0
 
    # Loop over all i stacks
    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):
                # Store the maximum of
                # popping j elements
                # up to the current stack
                # by popping k elements
                # from current stack and
                # j - k elements from all
                # previous stacks combined
                new_dp[j] = max(new_dp[j], stacks[i][k] + dp[j - k])
        dp = new_dp
 
    # dp[N] has the maximum sum
    return dp[N]
 
# Driver Program
if __name__ == '__main__':
    # Number of stacks
    S = 2
    # Length of each stack
    M = 4
 
    stacks = [
        [2, 6, 4, 5],
        [1, 6, 15, 10]
    ]
 
    # Maximum elements that
    # can be popped
    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)
    {
        // Constructing a dp vector of size N+1
        List<int> dp = new List<int>(new int[N + 1]);
 
        // Initialize the 0th index
        dp[0] = 0;
 
        // Loop over all i stacks
        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++)
                {
                    // Store the maximum of
                    // popping j elements
                    // up to the current stack
                    // by popping k elements
                    // from the current stack and
                    // j - k elements from all
                    // previous stacks combined
                    new_dp[j] = Math.Max(new_dp[j], stacks[i][k] + dp[j - k]);
                }
            }
            dp = new_dp;
        }
 
        // dp[N] has the maximum sum
        return dp[N];
    }
 
    public static void Main(string[] args)
    {
        // Number of stacks
        int S = 2;
        // Length of each stack
        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 });
 
        // Maximum elements that can be popped
        int N = 3;
 
        Console.WriteLine(MaximumSum(S, M, N, stacks));
    }
}
 
//This code is contributed by aeroabrar_31


Javascript




// Function for computing the
// maximum sum at the top of
// the stacks after popping at
// most N elements from S stack
function maximumSum(S, M, N, stacks) {
  // Constructing a dp vector of size N+1
  let dp = new Array(N + 1).fill(Number.MIN_SAFE_INTEGER);
 
  // Initialize the 0th index
  dp[0] = 0;
 
  // Loop over all i stacks
  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++) {
        // Store the maximum of
        // popping j elements
        // up to the current stack
        // by popping k elements
        // from current stack and
        // j - k elements from all
        // previous stacks combined
        new_dp[j] = Math.max(new_dp[j], stacks[i][k] + dp[j - k]);
      }
    }
    dp = new_dp;
  }
 
  // dp[N] has the maximum sum
  return dp[N];
}
 
// Driver Program
 
// Number of stacks
let S = 2;
// Length of each stack
let M = 4;
 
let stacks = [
  [2, 6, 4, 5],
  [1, 6, 15, 10]
];
 
// Maximum elements that
// can be popped
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)



Last Updated : 10 Aug, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads