Maximize cost to empty an array by removing contiguous subarrays of equal elements
Last Updated :
19 Apr, 2023
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 = 27
Input: 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++
#include <bits/stdc++.h>
using namespace std;
int dp[101][101][101];
int helper( int arr[], int left, int right,
int count, int m)
{
if (left > right)
return 0;
if (dp[left][right][count] != -1) {
return dp[left][right][count];
}
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]) {
ans = max(
ans,
helper(arr, left + 1,
i - 1, 0, m)
+ helper(arr, i, right,
count + 1, m));
}
}
dp[left][right][count] = ans;
return ans;
}
int maxPoints( int arr[], int n, int m)
{
int len = n;
memset (dp, -1, sizeof (dp));
return helper(arr, 0, len - 1, 0, m);
}
int main()
{
int arr[] = { 1, 3, 2, 2, 2, 3, 4, 3, 1 };
int M = 3;
int N = sizeof (arr) / sizeof (arr[0]);
cout << maxPoints(arr, N, M);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int [][][]dp = new int [ 101 ][ 101 ][ 101 ];
static int helper( int arr[], int left, int right,
int count, int m)
{
if (left > right)
return 0 ;
if (dp[left][right][count] != - 1 )
{
return dp[left][right][count];
}
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])
{
ans = Math.max(ans,
helper(arr, left + 1 ,
i - 1 , 0 , m) +
helper(arr, i, right,
count + 1 , m));
}
}
dp[left][right][count] = ans;
return ans;
}
static 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 ;
}
}
return helper(arr, 0 , len - 1 , 0 , m);
}
public static void main(String[] args)
{
int arr[] = { 1 , 3 , 2 , 2 , 2 , 3 , 4 , 3 , 1 };
int M = 3 ;
int N = arr.length;
System.out.print(maxPoints(arr, N, M));
}
}
|
Python3
dp = [[[ - 1 for x in range ( 101 )]
for y in range ( 101 )]
for z in range ( 101 )]
def helper(arr, left,
right, count, m):
if (left > right):
return 0
if (dp[left][right][count] ! = - 1 ):
return dp[left][right][count]
ans = ((count + 1 ) * m +
helper(arr, left + 1 ,
right, 0 , m))
for i in range (left + 1 ,
right + 1 ):
if (arr[i] = = arr[left]):
ans = ( max (ans, helper(arr, left + 1 ,
i - 1 , 0 , m) +
helper(arr, i, right,
count + 1 , m)))
dp[left][right][count] = ans
return ans
def maxPoints(arr, n, m):
length = n
global dp
return helper(arr, 0 ,
length - 1 , 0 , m)
if __name__ = = "__main__" :
arr = [ 1 , 3 , 2 , 2 ,
2 , 3 , 4 , 3 , 1 ]
M = 3
N = len (arr)
print (maxPoints(arr, N, M))
|
C#
using System;
class GFG{
static int [,,]dp = new int [101, 101, 101];
static int helper( int []arr, int left, int right,
int count, int m)
{
if (left > right)
return 0;
if (dp[left, right, count] != -1)
{
return dp[left, right, count];
}
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])
{
ans = Math.Max(ans,
helper(arr, left + 1,
i - 1, 0, m) +
helper(arr, i, right,
count + 1, m));
}
}
dp[left, right, count] = ans;
return ans;
}
static 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;
}
}
return helper(arr, 0, len - 1, 0, m);
}
public static void Main(String[] args)
{
int []arr = { 1, 3, 2, 2, 2, 3, 4, 3, 1 };
int M = 3;
int N = arr.Length;
Console.Write(maxPoints(arr, N, M));
}
}
|
Javascript
<script>
let 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 helper(arr, left, right, count, m)
{
if (left > right)
return 0;
if (dp[left][right][count] != -1)
{
return dp[left][right][count];
}
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])
{
ans = Math.max(ans,
helper(arr, left + 1,
i - 1, 0, m) +
helper(arr, i, right,
count + 1, m));
}
}
dp[left][right][count] = ans;
return ans;
}
function maxPoints(arr, n, m)
{
let len = arr.length;
return helper(arr, 0, len - 1, 0, m);
}
let arr = [ 1, 3, 2, 2, 2, 3, 4, 3, 1 ];
let M = 3;
let N = arr.length;
document.write(maxPoints(arr, N, M));
</script>
|
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++
#include <bits/stdc++.h>
using namespace std;
int maxPoints( int arr[], int n, int m)
{
int dp[n][n][n+1];
memset (dp, 0, sizeof (dp));
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]) {
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 dp[0][n-1][0];
}
int main()
{
int arr[] = { 1, 3, 2, 2, 2, 3, 4, 3, 1 };
int M = 3;
int N = sizeof (arr) / sizeof (arr[0]);
cout << maxPoints(arr, N, M);
return 0;
}
|
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 = 3
n = len (arr)
max_points = maxPoints(arr, n, m)
print (max_points)
|
Time Complexity: O(N4)
Auxiliary Space: O(N3)
Like Article
Suggest improvement
Previous
Shuffle array {a1, a2, .. an, b1, b2, .. bn} as {a1, b1, a2, b2, a3, b3, ……, an, bn} without using extra space
Share your thoughts in the comments
Please Login to comment...