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 neveropen!
