Maximize cost to empty an array by removing contiguous subarrays of equal elements

Given an array arr[] consisting of N integers and an integer M, the task is to find the maximum cost that can be obtained by performing the following operation any number of times.Â
In one operation, choose K contiguous elements with same value(where K ? 1) and remove them and cost of this operation is K * M.Â
Examples:Â
Input: arr[] = {1, 3, 2, 2, 2, 3, 4, 3, 1}, M = 3Â
Output: 27Â
Explanation:Â
Step 1: Remove three contiguous 2’s to modify arr[] = {1, 3, 3, 4, 3, 1}. Cost = 3 * 3 = 9Â
Step 2: Remove 4 to modify arr[] = {1, 3, 3, 3, 1}. Cost = 9 + 1 * 3 = 12Â
Step 3: Remove three contiguous 3’s to modify arr[] = {1, 1}. Cost = 12 + 3 * 3 = 21Â
Step 4: Remove two contiguous 1’s to modify arr[] = {}. Cost = 21 + 2 * 3 = 27Input: arr[] = {1, 2, 3, 4, 5, 6, 7}, M = 2Â
Output: 14
Approach: This problem can be solved using Dynamic Programming. Below are the steps:
- Initialize a 3D array dp[][][] such that dp[left][right][count], where left and right denotes operation between indices [left, right] and count is the number of elements to the left of arr[left] having same value as that of arr[left] and the count excludes arr[left].
- Now there are the following two possible choices:Â
- Ending the sequence to remove the elements of the same value including the starting element (i.e., arr[left]) and then continue from the next element onward.
- Continue the sequence to search between the indices [left + 1, right] for elements having the same value as arr[left](say index i), this enables us to continue the sequence.
- Make recursive calls from the new sequence and continue the process for the previous sequence.
- Print the maximum cost after all the above steps.
Below is the implementation of the above approach:
C++
// C++ program for the above approachÂ
#include <bits/stdc++.h>using namespace std;Â
// Initialize dp arrayint dp[101][101][101];Â
// Function that removes elements// from array to maximize the costint helper(int arr[], int left, int right,           int count, int m){    // Base case    if (left > right)        return 0;Â
    // Check if an answer is stored    if (dp[left][right][count] != -1) {        return dp[left][right][count];    }Â
    // Deleting count + 1 i.e. including    // the first element and starting a    // new sequence    int ans = (count + 1) * m              + helper(arr, left + 1,                       right, 0, m);Â
    for (int i = left + 1;         i <= right; ++i) {Â
        if (arr[i] == arr[left]) {Â
            // Removing [left + 1, i - 1]            // elements to continue with            // previous sequence            ans = max(                ans,                helper(arr, left + 1,                       i - 1, 0, m)                    + helper(arr, i, right,                             count + 1, m));        }    }Â
    // Store the result    dp[left][right][count] = ans;Â
    // Return answer    return ans;}Â
// Function to remove the elementsint maxPoints(int arr[], int n, int m){Â Â Â Â int len = n;Â Â Â Â memset(dp, -1, sizeof(dp));Â
    // Function Call    return helper(arr, 0, len - 1, 0, m);}Â
// Driver Codeint main(){    // Given array    int arr[] = { 1, 3, 2, 2, 2, 3, 4, 3, 1 };Â
    int M = 3;Â
    int N = sizeof(arr) / sizeof(arr[0]);Â
    // Function Call    cout << maxPoints(arr, N, M);    return 0;} |
Java
// Java program for the above approachimport java.util.*;Â
class GFG{Â
// Initialize dp arraystatic int [][][]dp = new int[101][101][101];Â
// Function that removes elements// from array to maximize the coststatic int helper(int arr[], int left, int right,                  int count, int m){         // Base case    if (left > right)        return 0;Â
    // Check if an answer is stored    if (dp[left][right][count] != -1)     {        return dp[left][right][count];    }Â
    // Deleting count + 1 i.e. including    // the first element and starting a    // new sequence    int ans = (count + 1) * m +              helper(arr, left + 1,                    right, 0, m);Â
    for(int i = left + 1; i <= right; ++i)    {        if (arr[i] == arr[left])         {                         // Removing [left + 1, i - 1]            // elements to continue with            // previous sequence            ans = Math.max(ans,                  helper(arr, left + 1,                         i - 1, 0, m) +                   helper(arr, i, right,                         count + 1, m));        }    }Â
    // Store the result    dp[left][right][count] = ans;Â
    // Return answer    return ans;}Â
// Function to remove the elementsstatic int maxPoints(int arr[], int n, int m){Â Â Â Â int len = n;Â Â Â Â for(int i = 0; i < 101; i++) Â Â Â Â {Â Â Â Â Â Â Â Â for(int j = 0; j < 101; j++)Â Â Â Â Â Â Â Â {Â Â Â Â Â Â Â Â Â Â Â Â for(int k = 0; k < 101; k++)Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â dp[i][j][k] = -1;Â Â Â Â Â Â Â Â }Â Â Â Â }Â
    // Function call    return helper(arr, 0, len - 1, 0, m);}Â
// Driver Codepublic static void main(String[] args){         // Given array    int arr[] = { 1, 3, 2, 2, 2, 3, 4, 3, 1 };Â
    int M = 3;Â
    int N = arr.length;Â
    // Function call    System.out.print(maxPoints(arr, N, M));}}Â
// This code is contributed by Amit Katiyar |
Python3
# Python3 program for # the above approachÂ
# Initialize dp arraydp = [[[-1 for x in range(101)]Â Â Â Â Â Â Â Â Â Â Â Â for y in range(101)]Â Â Â Â Â Â Â Â Â Â Â Â for z in range(101)]Â Â # Function that removes elements# from array to maximize the costdef helper(arr, left, Â Â Â Â Â Â Â Â Â Â Â right, count, m):Â
  # Base case  if (left > right):    return 0Â
  # Check if an answer is stored  if (dp[left][right][count] != -1):    return dp[left][right][count]Â
  # Deleting count + 1 i.e. including  # the first element and starting a  # new sequence  ans = ((count + 1) * m +          helper(arr, left + 1,                 right, 0, m))Â
  for i in range (left + 1,                  right + 1):Â
    if (arr[i] == arr[left]):Â
      # Removing [left + 1, i - 1]      # elements to continue with      # previous sequence      ans = (max(ans, helper(arr, left + 1,                             i - 1, 0, m) +                         helper(arr, i, right,                              count + 1, m)))Â
      # Store the result      dp[left][right][count] = ansÂ
      # Return answer      return ans  # Function to remove the elementsdef maxPoints(arr, n, m):  length = n  global dpÂ
  # Function Call  return helper(arr, 0,                 length - 1, 0, m)  # Driver Codeif __name__ == "__main__":Â
  # Given array  arr = [1, 3, 2, 2,          2, 3, 4, 3, 1]  M = 3  N = len(arr)Â
  # Function Call  print(maxPoints(arr, N, M))     # This code is contributed by Chitranayal |
C#
// C# program for the above approachusing System;Â
class GFG{Â
// Initialize dp arraystatic int [,,]dp = new int[101, 101, 101];Â
// Function that removes elements// from array to maximize the coststatic int helper(int []arr, int left, int right,                  int count, int m){         // Base case    if (left > right)        return 0;Â
    // Check if an answer is stored    if (dp[left, right, count] != -1)     {        return dp[left, right, count];    }Â
    // Deleting count + 1 i.e. including    // the first element and starting a    // new sequence    int ans = (count + 1) * m +               helper(arr, left + 1,                    right, 0, m);Â
    for(int i = left + 1; i <= right; ++i)    {        if (arr[i] == arr[left])         {                         // Removing [left + 1, i - 1]            // elements to continue with            // previous sequence            ans = Math.Max(ans,                  helper(arr, left + 1,                         i - 1, 0, m) +                   helper(arr, i, right,                         count + 1, m));        }    }Â
    // Store the result    dp[left, right, count] = ans;Â
    // Return answer    return ans;}Â
// Function to remove the elementsstatic int maxPoints(int []arr, int n, int m){Â Â Â Â int len = n;Â Â Â Â for(int i = 0; i < 101; i++) Â Â Â Â {Â Â Â Â Â Â Â Â for(int j = 0; j < 101; j++)Â Â Â Â Â Â Â Â {Â Â Â Â Â Â Â Â Â Â Â Â for(int k = 0; k < 101; k++)Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â dp[i, j, k] = -1;Â Â Â Â Â Â Â Â }Â Â Â Â }Â
    // Function call    return helper(arr, 0, len - 1, 0, m);}Â
// Driver Codepublic static void Main(String[] args){         // Given array    int []arr = { 1, 3, 2, 2, 2, 3, 4, 3, 1 };Â
    int M = 3;Â
    int N = arr.Length;Â
    // Function call    Console.Write(maxPoints(arr, N, M));}}Â
// This code is contributed by Amit Katiyar |
Javascript
<script>Â
// Javascript program for the above approachÂ
// Initialize dp arraylet dp = new Array(101);for(let i = 0; i < 101; i++){Â Â Â Â dp[i] = new Array(101);Â Â Â Â for(let j = 0; j < 101; j++)Â Â Â Â {Â Â Â Â Â Â Â Â dp[i][j] = new Array(101);Â Â Â Â Â Â Â Â for(let k = 0; k < 101; k++)Â Â Â Â Â Â Â Â {Â Â Â Â Â Â Â Â Â Â Â Â dp[i][j][k] = -1;Â Â Â Â Â Â Â Â }Â Â Â Â }}Â
// Function that removes elements// from array to maximize the costfunction helper(arr, left, right, count, m){         // Base case    if (left > right)        return 0;Â
    // Check if an answer is stored    if (dp[left][right][count] != -1)     {        return dp[left][right][count];    }Â
    // Deleting count + 1 i.e. including    // the first element and starting a    // new sequence    let ans = (count + 1) * m +               helper(arr, left + 1,                     right, 0, m);Â
    for(let i = left + 1; i <= right; ++i)    {        if (arr[i] == arr[left])         {                         // Removing [left + 1, i - 1]            // elements to continue with            // previous sequence            ans = Math.max(ans,                  helper(arr, left + 1,                         i - 1, 0, m) +                   helper(arr, i, right,                         count + 1, m));        }    }Â
    // Store the result    dp[left][right][count] = ans;Â
    // Return answer    return ans;}Â
// Function to remove the elementsfunction maxPoints(arr, n, m){    let len = arr.length;         // Function call    return helper(arr, 0, len - 1, 0, m);}Â
// Driver CodeÂ
// Given arraylet arr = [ 1, 3, 2, 2, 2, 3, 4, 3, 1 ];let M = 3;let N = arr.length;Â
// Function calldocument.write(maxPoints(arr, N, M));Â
// This code is contributed by avanitrachhadiya2155Â
</script> |
27
Time Complexity: O(N4)Â
Auxiliary Space: O(N3)Â
Efficient approach : Using DP Tabulation method ( Iterative approach )
The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memoization(top-down) because memoization method needs extra stack space of recursion calls.
Steps to solve this problem :
- Create a 3D DP table to store the solution of the subproblems.
- Initialize the table with base cases dp[i][i][1] = m + 1.
- Now Iterate over subproblems to get the value of current problem form previous computation of subproblems stored in DP.
- Return the final solution stored in dp[0][n-1][0].
Implementation :
C++
// C++ program for above approachÂ
#include <bits/stdc++.h>using namespace std;Â
// Function to remove the elementsint maxPoints(int arr[], int n, int m){    int dp[n][n][n+1];    memset(dp, 0, sizeof(dp));         // Initializing diagonal elements    for (int i = 0; i < n; i++) {        dp[i][i][1] = m + 1;    }         // Filling dp table      // get the current value from the previous      // computations of subproblems    for (int len = 2; len <= n; len++) {        for (int i = 0; i <= n-len; i++) {            int j = i + len - 1;                         // Deleting count + 1 i.e. including            // the first element and starting a            // new sequence            dp[i][j][0] = (len * m);                         for (int k = 1; k <= len; k++) {                if (arr[i] == arr[i+k-1]) {                    dp[i][j][k] = max(dp[i][j][k], dp[i+1][i+k-2][0] + dp[i+k][j][k+1]);                }                for (int l = 0; l < k; l++) {                    dp[i][j][k] = max(dp[i][j][k], dp[i][i+l][k] + dp[i+l+1][j][0]);                }            }        }    }         // Return the maximum points    return dp[0][n-1][0];}Â
// Driver Codeint main(){    // Given array    int arr[] = { 1, 3, 2, 2, 2, 3, 4, 3, 1 };Â
    int M = 3;Â
    int N = sizeof(arr) / sizeof(arr[0]);Â
    // Function Call    cout << maxPoints(arr, N, M);    return 0;}// this code is contributed by bhardwajji |
Java
import java.util.*;Â
public class Main {Â
    public static int maxPoints(int[] arr, int n, int m)    {        int[][][] dp = new int[n][n][n + 1];        for (int[][] layer : dp) {            for (int[] row : layer) {                Arrays.fill(row, 0);            }        }Â
        for (int i = 0; i < n; i++) {            dp[i][i][1] = m + 1;        }Â
        for (int len = 2; len <= n; len++) {            for (int i = 0; i <= n - len; i++) {                int j = i + len - 1;                dp[i][j][0] = (len * m);Â
                for (int k = 1; k <= len; k++) {                    if (arr[i] == arr[i + k - 1]) {                        if (i + k - 2 >= i && i + k < n                            && k + 1 <= n) {                            dp[i][j][k] = Math.max(                                dp[i][j][k],                                dp[i + 1][i + k - 2][0]                                    + dp[i + k][j][k + 1]);                        }                    }                    for (int l = 0; l < k; l++) {                        if (i + l <= j && i + l >= i                            && i + l + 1 <= j) {                            dp[i][j][k] = Math.max(                                dp[i][j][k],                                dp[i][i + l][k]                                    + dp[i + l + 1][j][0]);                        }                    }                }            }        }Â
        return dp[0][n - 1][0];    }Â
    public static void main(String[] args)    {        int[] arr = { 1, 3, 2, 2, 2, 3, 4, 3, 1 };        int m = 3;        int n = arr.length;        int maxPoints = maxPoints(arr, n, m);        System.out.println(maxPoints);    }} |
Python3
def maxPoints(arr, n, m):    dp = [[[0 for i in range(n + 1)] for j in range(n)] for k in range(n)]         for layer in dp:        for row in layer:            row[1] = m + 1         for i in range(n):        dp[i][i][1] = m + 1         for length in range(2, n + 1):        for i in range(n - length + 1):            j = i + length - 1            dp[i][j][0] = length * m                         for k in range(1, length + 1):                if arr[i] == arr[i + k - 1]:                    if i + k - 2 >= i and i + k < n and k + 1 <= n:                        dp[i][j][k] = max(dp[i][j][k],                         dp[i + 1][i + k - 2][0] + dp[i + k][j][k + 1])                                 for l in range(k):                    if i + l <= j and i + l >= i and i + l + 1 <= j:                        dp[i][j][k] = max(dp[i][j][k], dp[i][i +                                      l][k] + dp[i + l + 1][j][0])         return dp[0][n - 1][0]Â
Â
arr = [1, 3, 2, 2, 2, 3, 4, 3, 1]m = 3n = len(arr)max_points = maxPoints(arr, n, m)print(max_points) |
27
Time Complexity: O(N4)Â
Auxiliary Space: O(N3)Â
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 zambiatek!



