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>usingnamespacestd;// Initialize dp arrayintdp[101][101][101];// Function that removes elements// from array to maximize the costinthelper(intarr[], intleft, intright,           intcount, intm){    // Base case    if(left > right)        return0;    // Check if an answer is stored    if(dp[left][right][count] != -1) {        returndp[left][right][count];    }    // Deleting count + 1 i.e. including    // the first element and starting a    // new sequence    intans = (count + 1) * m              + helper(arr, left + 1,                       right, 0, m);    for(inti = 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    returnans;}// Function to remove the elementsintmaxPoints(intarr[], intn, intm){    intlen = n;    memset(dp, -1, sizeof(dp));    // Function Call    returnhelper(arr, 0, len - 1, 0, m);}// Driver Codeintmain(){    // Given array    intarr[] = { 1, 3, 2, 2, 2, 3, 4, 3, 1 };    intM = 3;    intN = sizeof(arr) / sizeof(arr[0]);    // Function Call    cout << maxPoints(arr, N, M);    return0;} | 
Java
| // Java program for the above approachimportjava.util.*;classGFG{// Initialize dp arraystaticint[][][]dp = newint[101][101][101];// Function that removes elements// from array to maximize the coststaticinthelper(intarr[], intleft, intright,                  intcount, intm){        // Base case    if(left > right)        return0;    // Check if an answer is stored    if(dp[left][right][count] != -1)     {        returndp[left][right][count];    }    // Deleting count + 1 i.e. including    // the first element and starting a    // new sequence    intans = (count + 1) * m +              helper(arr, left + 1,                    right, 0, m);    for(inti = 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    returnans;}// Function to remove the elementsstaticintmaxPoints(intarr[], intn, intm){    intlen = n;    for(inti = 0; i < 101; i++)     {        for(intj = 0; j < 101; j++)        {            for(intk = 0; k < 101; k++)                dp[i][j][k] = -1;        }    }    // Function call    returnhelper(arr, 0, len - 1, 0, m);}// Driver Codepublicstaticvoidmain(String[] args){        // Given array    intarr[] = { 1, 3, 2, 2, 2, 3, 4, 3, 1};    intM = 3;    intN = 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 =[[[-1forx inrange(101)]            fory inrange(101)]            forz inrange(101)] # Function that removes elements# from array to maximize the costdefhelper(arr, left,            right, count, m):  # Base case  if(left > right):    return0  # Check if an answer is stored  if(dp[left][right][count] !=-1):    returndp[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))  fori inrange(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      returnans # Function to remove the elementsdefmaxPoints(arr, n, m):  length =n  globaldp  # Function Call  returnhelper(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 approachusingSystem;classGFG{// Initialize dp arraystaticint[,,]dp = newint[101, 101, 101];// Function that removes elements// from array to maximize the coststaticinthelper(int[]arr, intleft, intright,                  intcount, intm){        // Base case    if(left > right)        return0;    // Check if an answer is stored    if(dp[left, right, count] != -1)     {        returndp[left, right, count];    }    // Deleting count + 1 i.e. including    // the first element and starting a    // new sequence    intans = (count + 1) * m +               helper(arr, left + 1,                    right, 0, m);    for(inti = 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    returnans;}// Function to remove the elementsstaticintmaxPoints(int[]arr, intn, intm){    intlen = n;    for(inti = 0; i < 101; i++)     {        for(intj = 0; j < 101; j++)        {            for(intk = 0; k < 101; k++)                dp[i, j, k] = -1;        }    }    // Function call    returnhelper(arr, 0, len - 1, 0, m);}// Driver CodepublicstaticvoidMain(String[] args){        // Given array    int[]arr = { 1, 3, 2, 2, 2, 3, 4, 3, 1 };    intM = 3;    intN = 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 = newArray(101);for(let i = 0; i < 101; i++){    dp[i] = newArray(101);    for(let j = 0; j < 101; j++)    {        dp[i][j] = newArray(101);        for(let k = 0; k < 101; k++)        {            dp[i][j][k] = -1;        }    }}// Function that removes elements// from array to maximize the costfunctionhelper(arr, left, right, count, m){        // Base case    if(left > right)        return0;    // Check if an answer is stored    if(dp[left][right][count] != -1)     {        returndp[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    returnans;}// Function to remove the elementsfunctionmaxPoints(arr, n, m){    let len = arr.length;        // Function call    returnhelper(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>usingnamespacestd;// Function to remove the elementsintmaxPoints(intarr[], intn, intm){    intdp[n][n][n+1];    memset(dp, 0, sizeof(dp));        // Initializing diagonal elements    for(inti = 0; i < n; i++) {        dp[i][i][1] = m + 1;    }        // Filling dp table      // get the current value from the previous      // computations of subproblems    for(intlen = 2; len <= n; len++) {        for(inti = 0; i <= n-len; i++) {            intj = i + len - 1;                        // Deleting count + 1 i.e. including            // the first element and starting a            // new sequence            dp[i][j][0] = (len * m);                        for(intk = 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(intl = 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    returndp[0][n-1][0];}// Driver Codeintmain(){    // Given array    intarr[] = { 1, 3, 2, 2, 2, 3, 4, 3, 1 };    intM = 3;    intN = sizeof(arr) / sizeof(arr[0]);    // Function Call    cout << maxPoints(arr, N, M);    return0;}// this code is contributed by bhardwajji | 
Java
| importjava.util.*;publicclassMain {    publicstaticintmaxPoints(int[] arr, intn, intm)    {        int[][][] dp = newint[n][n][n + 1];        for(int[][] layer : dp) {            for(int[] row : layer) {                Arrays.fill(row, 0);            }        }        for(inti = 0; i < n; i++) {            dp[i][i][1] = m + 1;        }        for(intlen = 2; len <= n; len++) {            for(inti = 0; i <= n - len; i++) {                intj = i + len - 1;                dp[i][j][0] = (len * m);                for(intk = 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(intl = 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]);                        }                    }                }            }        }        returndp[0][n - 1][0];    }    publicstaticvoidmain(String[] args)    {        int[] arr = { 1, 3, 2, 2, 2, 3, 4, 3, 1};        intm = 3;        intn = arr.length;        intmaxPoints = maxPoints(arr, n, m);        System.out.println(maxPoints);    }} | 
Python3
| defmaxPoints(arr, n, m):    dp =[[[0fori inrange(n +1)] forj inrange(n)] fork inrange(n)]        forlayer indp:        forrow inlayer:            row[1] =m +1        fori inrange(n):        dp[i][i][1] =m +1        forlength inrange(2, n +1):        fori inrange(n -length +1):            j =i +length -1            dp[i][j][0] =length *m                        fork inrange(1, length +1):                ifarr[i] ==arr[i +k -1]:                    ifi +k -2>=i andi +k < n andk +1<=n:                        dp[i][j][k] =max(dp[i][j][k],                         dp[i +1][i +k -2][0] +dp[i +k][j][k +1])                                forl inrange(k):                    ifi +l <=j andi +l >=i andi +l +1<=j:                        dp[i][j][k] =max(dp[i][j][k], dp[i][i +                                      l][k] +dp[i +l +1][j][0])        returndp[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!
 
				 
					


