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 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
// 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
# 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#
// 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 |
Javascript
<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++
// 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 |
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) |
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 neveropen!