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++ program for the above approach #include <bits/stdc++.h> using namespace std;
// Initialize dp array int dp[101][101][101];
// Function that removes elements // from array to maximize the cost 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 = 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 elements int 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 Code int 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 program for the above approach import java.util.*;
class GFG{
// Initialize dp array static int [][][]dp = new int [ 101 ][ 101 ][ 101 ];
// Function that removes elements // from array to maximize the cost static 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 elements 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 ;
}
}
// Function call
return helper(arr, 0 , len - 1 , 0 , m);
} // Driver Code public 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 program for # the above approach # Initialize dp array dp = [[[ - 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 cost def 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 elements def maxPoints(arr, n, m):
length = n
global dp
# Function Call
return helper(arr, 0 ,
length - 1 , 0 , m)
# Driver Code if __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# program for the above approach using System;
class GFG{
// Initialize dp array static int [,,]dp = new int [101, 101, 101];
// Function that removes elements // from array to maximize the cost static 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 elements 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;
}
}
// Function call
return helper(arr, 0, len - 1, 0, m);
} // Driver Code public 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 |
<script> // Javascript program for the above approach // Initialize dp array 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 that removes elements // from array to maximize the cost function 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 elements function maxPoints(arr, n, m)
{ let len = arr.length;
// Function call
return helper(arr, 0, len - 1, 0, m);
} // Driver Code // Given array let arr = [ 1, 3, 2, 2, 2, 3, 4, 3, 1 ]; let M = 3; let N = arr.length; // Function call document.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++ program for above approach #include <bits/stdc++.h> using namespace std;
// Function to remove the elements int 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 Code int 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 |
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);
}
} |
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)
|
27
Time Complexity: O(N4)
Auxiliary Space: O(N3)