Maximum points by removing Identical Items
Last Updated :
23 Dec, 2023
Given an array arr[] of size N (1 <= N <= 100), which consists of positive numbers representing different items, two items in the array will be treated as identical if arr[i] == arr[j]. In each round, you can select k consecutive identical items, then remove all identical items, and gain k*k points. The task is to determine the maximum number of points that can be obtained by making the array empty.
Examples:
Input: arr = {1,3,2,2,2,3,4,3,1}
Output: 23
Explanation: {1, 3, 2, 2, 2, 3, 4, 3, 1}
{1, 3, 3, 4, 3, 1} (3*3=9 points)
{1, 3, 3, 3, 1} (1*1=1 points)
{1, 1] (3*3=9 points)
{} (2*2=4 points)
Input: arr = {1,1,1}
Output: 9
Input: arr = {2}
Output: 1
Approach: To solve the problem follow the below steps:
- Let dp(l, r, k) represent the maximum points we can obtain from a sequence of items within the range [l, r] if we have an additional k items of the same type as the item at position l on the left side.
- For example: if we have a sequence of items {3, 3, 1, 3, 3}, then dp(l=3, r=4, k=2) is the maximum points we can obtain from the subsequence {3, 3} if we have an extra 2 items of the same type as the item at position 3 on the left side, effectively making it {3, 3, 3, 3}.
- Now, let's consider our options:
- Option 1 is to remove all items with the same type as arr[l]. The total points we can get in this case are dp(l+1, r, 0) + (k+1)*(k+1) (k left items and the lth item have the same type).
- Other option,is that we try to merge non-contiguous items of the same type together, by:
- Finding the index j, where l+1 <= j <= r such that arr[j] == arr[l].
- The total points we can get in this case are dp(j, r, k+1) + dp(l+1, j-1, 0).
- Choose the option with the maximum score to maximize the points.
Illustration of Options:
ExampleBelow is the implementation of the above idea:
C++
// C++ code for the above approach:
#include <iostream>
#include <vector>
using namespace std;
// Memoization table to store computed results
int memo[200][200][200] = {};
int dp(vector<int>& arr, int l, int r, int k)
{
// Base case: no elements left
if (l > r)
return 0;
// Return memoized result, if available.
if (memo[l][r][k] > 0)
return memo[l][r][k];
int lOrginal = l, kOrginal = k;
while (l + 1 <= r && arr[l] == arr[l + 1]) {
// Increase both `l` and `k` if they have
// consecutive identical items with `arr[l]`
l += 1;
k += 1;
}
// Option 1: Remove all elements which
// have the same item as `arr[l]`
int ans = (k + 1) * (k + 1) + dp(arr, l + 1, r, 0);
// Try to merge non-contiguous items of
// the same type together,
for (int m = l + 1; m <= r; ++m) {
if (arr[m] == arr[l])
ans = max(ans, dp(arr, m, r, k + 1)
+ dp(arr, l + 1, m - 1, 0));
}
// Memoize the result and return it
return memo[lOrginal][r][kOrginal] = ans;
}
// Driver code
int main()
{
vector<int> arr = { 1, 3, 2, 2, 2, 3, 4, 3, 1 };
int maxPoints = dp(arr, 0, arr.size() - 1, 0);
// Function Call
cout << "Maximum points: " << maxPoints << endl;
return 0;
}
Java
import java.util.Arrays;
public class MaximumPoints {
// Memoization table to store computed results
static int[][][] memo = new int[200][200][200];
public static int dp(int[] arr, int l, int r, int k)
{
// Base case: no elements left
if (l > r)
return 0;
// Return memoized result, if available.
if (memo[l][r][k] > 0)
return memo[l][r][k];
int lOriginal = l, kOriginal = k;
while (l + 1 <= r && arr[l] == arr[l + 1]) {
// Increase both `l` and `k` if they have
// consecutive identical items with `arr[l]`
l += 1;
k += 1;
}
// Option 1: Remove all elements which have the same
// item as `arr[l]`
int ans = (k + 1) * (k + 1) + dp(arr, l + 1, r, 0);
// Try to merge non-contiguous items of the same
// type together
for (int m = l + 1; m <= r; ++m) {
if (arr[m] == arr[l]) {
ans = Math.max(
ans, dp(arr, m, r, k + 1)
+ dp(arr, l + 1, m - 1, 0));
}
}
// Memoize the result and return it
return memo[lOriginal][r][kOriginal] = ans;
}
public static void main(String[] args)
{
int[] arr = { 1, 3, 2, 2, 2, 3, 4, 3, 1 };
int maxPoints = dp(arr, 0, arr.length - 1, 0);
// Function Call
System.out.println("Maximum points: " + maxPoints);
}
}
Python3
# Function to calculate maximum points
def dp(arr, l, r, k, memo):
# Base case: no elements left
if l > r:
return 0
# Return memoized result, if available
if memo[l][r][k] > 0:
return memo[l][r][k]
l_orginal, k_orginal = l, k
while l + 1 <= r and arr[l] == arr[l + 1]:
# Increase both `l` and `k` if they have
# consecutive identical items with `arr[l]`
l += 1
k += 1
# Option 1: Remove all elements which
# have the same item as `arr[l]`
ans = (k + 1) * (k + 1) + dp(arr, l + 1, r, 0, memo)
# Try to merge non-contiguous items of
# the same type together
for m in range(l + 1, r + 1):
if arr[m] == arr[l]:
ans = max(ans, dp(arr, m, r, k + 1, memo) + dp(arr, l + 1, m - 1, 0, memo))
# Memoize the result and return it
memo[l_orginal][r][k_orginal] = ans
return ans
# Driver code
if __name__ == "__main__":
arr = [1, 3, 2, 2, 2, 3, 4, 3, 1]
n = len(arr)
memo = [[[0] * 200 for _ in range(200)] for _ in range(200)]
maxPoints = dp(arr, 0, n - 1, 0, memo)
# Function Call
print(f"Maximum points: {maxPoints}")
C#
// C# Implementation
using System;
public class MaximumPoints
{
// Memoization table to store computed results
static int[,,] memo = new int[200, 200, 200];
public static int Dp(int[] arr, int l, int r, int k)
{
// Base case: no elements left
if (l > r)
return 0;
// Return memoized result, if available.
if (memo[l, r, k] > 0)
return memo[l, r, k];
int lOriginal = l, kOriginal = k;
while (l + 1 <= r && arr[l] == arr[l + 1])
{
// Increase both `l` and `k` if they have
// consecutive identical items with `arr[l]`
l += 1;
k += 1;
}
// Option 1: Remove all elements which have the same
// item as `arr[l]`
int ans = (k + 1) * (k + 1) + Dp(arr, l + 1, r, 0);
// Try to merge non-contiguous items of the same
// type together
for (int m = l + 1; m <= r; ++m)
{
if (arr[m] == arr[l])
{
ans = Math.Max(
ans, Dp(arr, m, r, k + 1)
+ Dp(arr, l + 1, m - 1, 0));
}
}
// Memoize the result and return it
return memo[lOriginal, r, kOriginal] = ans;
}
public static void Main(string[] args)
{
int[] arr = { 1, 3, 2, 2, 2, 3, 4, 3, 1 };
int maxPoints = Dp(arr, 0, arr.Length - 1, 0);
// Function Call
Console.WriteLine("Maximum points: " + maxPoints);
}
}
// This code is contributed by Tapesh(tapeshdua420)
JavaScript
let memo = new Array(200).fill(null).map(() =>
new Array(200).fill(null).map(() => new Array(200).fill(0))
);
function GFG(arr, l, r, k) {
// Base case: no elements left
if (l > r) return 0;
// Return memoized result
if (memo[l][r][k] > 0) return memo[l][r][k];
let lOriginal = l,
kOriginal = k;
while (l + 1 <= r && arr[l] === arr[l + 1]) {
// Increase both `l` and `k` if they have
l += 1;
k += 1;
}
// Option 1: Remove all elements which have the same item as `arr[l]`
let ans = (k + 1) * (k + 1) + GFG(arr, l + 1, r, 0);
// Try to merge non-contiguous items of the same type together
for (let m = l + 1; m <= r; ++m) {
if (arr[m] === arr[l]) {
ans = Math.max(
ans,
GFG(arr, m, r, k + 1) + GFG(arr, l + 1, m - 1, 0)
);
}
}
// Memoize the result and return it
return (memo[lOriginal][r][kOriginal] = ans);
}
let arr = [1, 3, 2, 2, 2, 3, 4, 3, 1];
let maxPoints = GFG(arr, 0, arr.length - 1, 0);
// Function Call
console.log("Maximum points: " + maxPoints);
Time Complexity: O(N4), there are total N3 dp states, each state needs a loop O(N) to compute the result. So total complexity is O(N4).
Auxiliary Space: O(N3)
Similar Reads
Maximum distinct elements after removing k elements Given an array arr[] containing n elements. The task is to find the maximum count of distinct elements (non-repeating) after removing k elements from the array. Note: 1 <= k <= n.Examples: Input : arr[] = [5, 7, 5, 5, 1, 2, 2], k = 3Output : 4Explanation: Remove 2 occurrences of element 5 and
12 min read
Maximum occurring integer in given ranges Given two arrays L[] and R[] of size N where L[i] and R[i] (0 ? L[i], R[i] < 106)denotes a range of numbers, the task is to find the maximum occurred integer in all the ranges. If more than one such integer exists, print the smallest one. Examples: Input: L[] = {1, 4, 3, 1}, R[] = {15, 8, 5, 4}Ou
9 min read
Minimum number of distinct elements after removing m items Given an array of items, an i-th index element denotes the item id's, and given a number m, the task is to remove m elements such that there should be minimum distinct id's left. Print the number of distinct id's. Examples: Input : arr[] = { 2, 2, 1, 3, 3, 3} m = 3Output : 1Remove 1 and both 2's.So,
15+ min read
Minimum number of distinct elements after removing M items | Set 2 Given an array of items, an ith index element denotes the item idâs, and given a number m, the task is to remove m elements such that there should be minimum distinct idâs left. Print the number of distinct idâs. Examples: Input: arr[] = { 2, 2, 1, 3, 3, 3} m = 3Output: 1Explanation:Remove 1 and bot
7 min read
Find maximum frequency of any point across all ranges Given a 2D array ranges[][] of size N denoting N ranges of points. Find the maximum frequency of any point across all the ranges. Examples:Input: ranges[][] = {{1, 4}, {3, 7}, {9, 10}, {2, 11}, {4, 6}}Output: 4Explanation: Point 1 occurs 1 timesPoint 2 occurs 2 timesPoint 3 occurs 3 timesPoint 4 occ
6 min read