Maximum score possible after performing given operations on an Array

Given an array A of size N, the task is to find the maximum score possible of this array. The score of an array is calculated by performing the following operations on the array N times: 
 

  1. If the operation is odd-numbered, the score is incremented by the sum of all elements of the current array. 
     
  2. If the operation is even-numbered, the score is decremented by the sum of all elements of the current array. 
     
  3. After every operation, either remove the first or the last element of the remaining array. 
     

Examples: 
 

Input: A = {1, 2, 3, 4, 2, 6} 
Output: 13 
Explanation: 
The optimal operations are: 
1. Operation 1 is odd. 
-> So add the sum of the array to the score: Score = 0 + 18 = 18 
-> remove 6 from last, 
-> new array A = [1, 2, 3, 4, 2] 
2. Operation 2 is even. 
-> So subtract the sum of the array from the score: Score = 18 – 12 = 6 
-> remove 2 from last, 
-> new array A = [1, 2, 3, 4] 
3. Operation 1 is odd. 
-> So add the sum of the array to the score: Score = 6 + 10 = 16 
-> remove 4 from last, 
-> new array A = [1, 2, 3] 
4. Operation 4 is even. 
-> So subtract the sum of the array from the score: Score = 16 – 6 = 10 
-> remove 1 from start, 
-> new array A = [2, 3] 
5. Operation 5 is odd. 
-> So add the sum of the array to the score: Score = 10 + 5 = 15 
-> remove 3 from last, 
-> new array A = [2] 
6. Operation 6 is even. 
-> So subtract the sum of the array from the score: Score = 15 – 2 = 13 
-> remove 2 from first, 
-> new array A = [] 
The array is empty so no further operations are possible.
Input: A = [5, 2, 2, 8, 1, 16, 7, 9, 12, 4] 
Output: 50 
 

 

Naive approach 
 



  1. In each operation, we have to remove either the leftmost or the rightmost element. A simple way would be to consider all possible ways to remove elements and for each branch compute the score and find the maximum score out of all. This can simply be done using recursion
     
  2. The information we need to keep in each step would be 
    • The remaining array [l, r], where l represents the leftmost index and r the rightmost,
    • The operation number, and
    • The current score.
  3. In order to calculate the sum of any array from [l, r] in each recursive step optimally, we will keep a prefix sum array
    Using prefix sum array, new sum from [l, r] can be calculated in O(1) as: 
     

Sum(l, r) = prefix_sum[r] – prefix_sum[l-1] 
 

  1.  

Below is the implementation of the above approach: 
 

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program to find the maximum
// score after given operations
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to calculate
// maximum score recursively
int maxScore(
    int l, int r,
    int prefix_sum[],
    int num)
{
 
    // Base case
    if (l > r)
        return 0;
 
    // Sum of array in range (l, r)
    int current_sum
        = prefix_sum[r]
          - (l - 1 >= 0
                 ? prefix_sum[l - 1]
                 : 0);
 
    // If the operation is even-numbered
    // the score is decremented
    if (num % 2 == 0)
        current_sum *= -1;
 
    // Exploring all paths, by removing
    // leftmost and rightmost element
    // and selecting the maximum value
    return current_sum
           + max(
                 maxScore(
                     l + 1, r,
                     prefix_sum,
                     num + 1),
                 maxScore(
                     l, r - 1,
                     prefix_sum,
                     num + 1));
}
 
// Function to find the max score
int findMaxScore(int a[], int n)
{
    // Prefix sum array
    int prefix_sum[n] = { 0 };
 
    prefix_sum[0] = a[0];
 
    // Calculating prefix_sum
    for (int i = 1; i < n; i++) {
        prefix_sum[i]
            = prefix_sum[i - 1] + a[i];
    }
 
    return maxScore(0, n - 1,
                    prefix_sum, 1);
}
 
// Driver code
int main()
{
    int n = 6;
    int A[n] = { 1, 2, 3, 4, 2, 6 };
 
    cout << findMaxScore(A, n);
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program to find the maximum
// score after given operations
import java.util.*;
 
class GFG{
 
// Function to calculate
// maximum score recursively
static int maxScore(
    int l, int r,
    int prefix_sum[],
    int num)
{
 
    // Base case
    if (l > r)
        return 0;
 
    // Sum of array in range (l, r)
    int current_sum
        = prefix_sum[r]
        - (l - 1 >= 0
                ? prefix_sum[l - 1]
                : 0);
 
    // If the operation is even-numbered
    // the score is decremented
    if (num % 2 == 0)
        current_sum *= -1;
 
    // Exploring all paths, by removing
    // leftmost and rightmost element
    // and selecting the maximum value
    return current_sum
        + Math.max(maxScore(l + 1, r,
                            prefix_sum,
                            num + 1),
                    maxScore(l, r - 1,
                            prefix_sum,
                            num + 1));
}
 
// Function to find the max score
static int findMaxScore(int a[], int n)
{
    // Prefix sum array
    int prefix_sum[] = new int[n];
 
    prefix_sum[0] = a[0];
 
    // Calculating prefix_sum
    for (int i = 1; i < n; i++) {
        prefix_sum[i]
            = prefix_sum[i - 1] + a[i];
    }
 
    return maxScore(0, n - 1,
                    prefix_sum, 1);
}
 
// Driver code
public static void main(String[] args)
{
    int n = 6;
    int A[] = { 1, 2, 3, 4, 2, 6 };
 
    System.out.print(findMaxScore(A, n));
}
}
 
// This code is contributed by sapnasingh4991

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 program to find the maximum
# score after given operations
 
# Function to calculate maximum
# score recursively
def maxScore(l, r, prefix_sum, num):
     
    # Base case
    if (l > r):
        return 0;
 
    # Sum of array in range (l, r)
    if((l - 1) >= 0):
        current_sum = (prefix_sum[r] -
                       prefix_sum[l - 1])
    else:
        current_sum = prefix_sum[r] - 0
     
    # If the operation is even-numbered
    # the score is decremented
    if (num % 2 == 0):
        current_sum *= -1;
 
    # Exploring all paths, by removing
    # leftmost and rightmost element
    # and selecting the maximum value
    return current_sum + max(maxScore(l + 1, r,
                                      prefix_sum,
                                      num + 1),
                             maxScore(l, r - 1,
                                      prefix_sum,
                                      num + 1));
 
# Function to find the max score
def findMaxScore(a, n):
 
    # Prefix sum array
    prefix_sum = [0] * n
 
    prefix_sum[0] = a[0]
 
    # Calculating prefix_sum
    for i in range(1, n):
        prefix_sum[i] = prefix_sum[i - 1] + a[i];
         
    return maxScore(0, n - 1, prefix_sum, 1);
 
# Driver code
n = 6;
A = [ 1, 2, 3, 4, 2, 6 ]
ans = findMaxScore(A, n)
 
print(ans)
 
# This code is contributed by SoumikMondal

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program to find the maximum
// score after given operations
using System;
 
class GFG{
  
// Function to calculate
// maximum score recursively
static int maxScore(
    int l, int r,
    int []prefix_sum,
    int num)
{
  
    // Base case
    if (l > r)
        return 0;
  
    // Sum of array in range (l, r)
    int current_sum
        = prefix_sum[r]
        - (l - 1 >= 0
                ? prefix_sum[l - 1]
                : 0);
  
    // If the operation is even-numbered
    // the score is decremented
    if (num % 2 == 0)
        current_sum *= -1;
  
    // Exploring all paths, by removing
    // leftmost and rightmost element
    // and selecting the maximum value
    return current_sum
        + Math.Max(maxScore(l + 1, r,
                            prefix_sum,
                            num + 1),
                    maxScore(l, r - 1,
                            prefix_sum,
                            num + 1));
}
  
// Function to find the max score
static int findMaxScore(int []a, int n)
{
    // Prefix sum array
    int []prefix_sum = new int[n];
  
    prefix_sum[0] = a[0];
  
    // Calculating prefix_sum
    for (int i = 1; i < n; i++) {
        prefix_sum[i]
            = prefix_sum[i - 1] + a[i];
    }
  
    return maxScore(0, n - 1,
                    prefix_sum, 1);
}
  
// Driver code
public static void Main(String[] args)
{
    int n = 6;
    int []A = { 1, 2, 3, 4, 2, 6 };
  
    Console.Write(findMaxScore(A, n));
}
}
 
// This code is contributed by 29AjayKumar

chevron_right


Output: 

13

 

Time complexity: O(2N)
Efficient approach 
 

  • In the previous approach it can be observed that we are calculating same subproblems many times, i.e. it follows the property of Overlapping Subproblems. So we can use Dynamic programming to solve the problem 
     
  • In the recursive solution stated above, we only need to add memoization using a dp table. The states will be: 
     

DP table states = dp[l][r][num]
where l and r represent the endpoints of the current array and num represents the operation number. 
 

  •  

Below is the implementation of the Memoization approach of the recursive code: 
 

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program to find the maximum
// Score after given operations
 
#include <bits/stdc++.h>
using namespace std;
 
// Memoizing by the use of a table
int dp[100][100][100];
 
// Function to calculate maximum score
int MaximumScoreDP(int l, int r,
                   int prefix_sum[],
                   int num)
{
    // Bse case
    if (l > r)
        return 0;
 
    // If the same state has
    // already been computed
    if (dp[l][r][num] != -1)
        return dp[l][r][num];
 
    // Sum of array in range (l, r)
    int current_sum
        = prefix_sum[r]
          - (l - 1 >= 0
                 ? prefix_sum[l - 1]
                 : 0);
 
    // If the operation is even-numbered
    // the score is decremented
    if (num % 2 == 0)
        current_sum *= -1;
 
    // Exploring all paths, and storing
    // maximum value in DP table to avoid
    // further repetitive recursive calls
    dp[l][r][num] = current_sum
                    + max(
                          MaximumScoreDP(
                              l + 1, r,
                              prefix_sum,
                              num + 1),
                          MaximumScoreDP(
                              l, r - 1,
                              prefix_sum,
                              num + 1));
 
    return dp[l][r][num];
}
 
// Function to find the max score
int findMaxScore(int a[], int n)
{
    // Prefix sum array
    int prefix_sum[n] = { 0 };
 
    prefix_sum[0] = a[0];
 
    // Calculating prefix_sum
    for (int i = 1; i < n; i++) {
        prefix_sum[i]
            = prefix_sum[i - 1] + a[i];
    }
 
    // Initialising the DP table,
    // -1 represents the subproblem
    // hasn't been solved yet
    memset(dp, -1, sizeof(dp));
 
    return MaximumScoreDP(
        0, n - 1,
        prefix_sum, 1);
}
 
// Driver code
int main()
{
    int n = 6;
    int A[n] = { 1, 2, 3, 4, 2, 6 };
 
    cout << findMaxScore(A, n);
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program to find the maximum
// Score after given operations
 
 
class GFG{
  
// Memoizing by the use of a table
static int [][][]dp = new int[100][100][100];
  
// Function to calculate maximum score
static int MaximumScoreDP(int l, int r,
                   int prefix_sum[],
                   int num)
{
    // Bse case
    if (l > r)
        return 0;
  
    // If the same state has
    // already been computed
    if (dp[l][r][num] != -1)
        return dp[l][r][num];
  
    // Sum of array in range (l, r)
    int current_sum
        = prefix_sum[r]
          - (l - 1 >= 0
                 ? prefix_sum[l - 1]
                 : 0);
  
    // If the operation is even-numbered
    // the score is decremented
    if (num % 2 == 0)
        current_sum *= -1;
  
    // Exploring all paths, and storing
    // maximum value in DP table to avoid
    // further repetitive recursive calls
    dp[l][r][num] = current_sum
                    + Math.max(
                          MaximumScoreDP(
                              l + 1, r,
                              prefix_sum,
                              num + 1),
                          MaximumScoreDP(
                              l, r - 1,
                              prefix_sum,
                              num + 1));
  
    return dp[l][r][num];
}
  
// Function to find the max score
static int findMaxScore(int a[], int n)
{
    // Prefix sum array
    int []prefix_sum = new int[n];
  
    prefix_sum[0] = a[0];
  
    // Calculating prefix_sum
    for (int i = 1; i < n; i++) {
        prefix_sum[i]
            = prefix_sum[i - 1] + a[i];
    }
  
    // Initialising the DP table,
    // -1 represents the subproblem
    // hasn't been solved yet
    for(int i = 0;i<100;i++){
       for(int j = 0;j<100;j++){
           for(int l=0;l<100;l++)
           dp[i][j][l]=-1;
       }
   }
  
    return MaximumScoreDP(
        0, n - 1,
        prefix_sum, 1);
}
  
// Driver code
public static void main(String[] args)
{
    int n = 6;
    int A[] = { 1, 2, 3, 4, 2, 6 };
  
    System.out.print(findMaxScore(A, n));
}
}
 
// This code contributed by sapnasingh4991

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# python3 program to find the maximum
# Score after given operations
 
# Memoizing by the use of a table
dp = [[[-1 for x in range(100)]for y in range(100)]for z in range(100)]
 
# Function to calculate maximum score
 
 
def MaximumScoreDP(l, r, prefix_sum,
                   num):
 
    # Bse case
    if (l > r):
        return 0
 
    # If the same state has
    # already been computed
    if (dp[l][r][num] != -1):
        return dp[l][r][num]
 
    # Sum of array in range (l, r)
    current_sum = prefix_sum[r]
    if (l - 1 >= 0):
        current_sum -= prefix_sum[l - 1]
 
    # If the operation is even-numbered
    # the score is decremented
    if (num % 2 == 0):
        current_sum *= -1
 
    # Exploring all paths, and storing
    # maximum value in DP table to avoid
    # further repetitive recursive calls
    dp[l][r][num] = (current_sum
                     + max(
                         MaximumScoreDP(
                             l + 1, r,
                             prefix_sum,
                             num + 1),
                         MaximumScoreDP(
                             l, r - 1,
                             prefix_sum,
                             num + 1)))
 
    return dp[l][r][num]
 
 
# Function to find the max score
def findMaxScore(a, n):
 
    # Prefix sum array
    prefix_sum = [0]*n
 
    prefix_sum[0] = a[0]
 
    # Calculating prefix_sum
    for i in range(1, n):
        prefix_sum[i] = prefix_sum[i - 1] + a[i]
 
    # Initialising the DP table,
    # -1 represents the subproblem
    # hasn't been solved yet
    global dp
 
    return MaximumScoreDP(
        0, n - 1,
        prefix_sum, 1)
 
 
# Driver code
if __name__ == "__main__":
 
    n = 6
    A = [1, 2, 3, 4, 2, 6]
 
    print(findMaxScore(A, n))

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program to find the maximum
// Score after given operations
  
  
using System;
 
public class GFG{
   
// Memoizing by the use of a table
static int [,,]dp = new int[100,100,100];
   
// Function to calculate maximum score
static int MaximumScoreDP(int l, int r,
                   int []prefix_sum,
                   int num)
{
    // Bse case
    if (l > r)
        return 0;
   
    // If the same state has
    // already been computed
    if (dp[l,r,num] != -1)
        return dp[l,r,num];
   
    // Sum of array in range (l, r)
    int current_sum
        = prefix_sum[r]
          - (l - 1 >= 0
                 ? prefix_sum[l - 1]
                 : 0);
   
    // If the operation is even-numbered
    // the score is decremented
    if (num % 2 == 0)
        current_sum *= -1;
   
    // Exploring all paths, and storing
    // maximum value in DP table to avoid
    // further repetitive recursive calls
    dp[l,r,num] = current_sum
                    + Math.Max(
                          MaximumScoreDP(
                              l + 1, r,
                              prefix_sum,
                              num + 1),
                          MaximumScoreDP(
                              l, r - 1,
                              prefix_sum,
                              num + 1));
   
    return dp[l,r,num];
}
   
// Function to find the max score
static int findMaxScore(int []a, int n)
{
    // Prefix sum array
    int []prefix_sum = new int[n];
   
    prefix_sum[0] = a[0];
   
    // Calculating prefix_sum
    for (int i = 1; i < n; i++) {
        prefix_sum[i]
            = prefix_sum[i - 1] + a[i];
    }
   
    // Initialising the DP table,
    // -1 represents the subproblem
    // hasn't been solved yet
    for(int i = 0;i<100;i++){
       for(int j = 0;j<100;j++){
           for(int l=0;l<100;l++)
           dp[i,j,l]=-1;
       }
   }
   
    return MaximumScoreDP(
        0, n - 1,
        prefix_sum, 1);
}
   
// Driver code
public static void Main(String[] args)
{
    int n = 6;
    int []A = { 1, 2, 3, 4, 2, 6 };
   
    Console.Write(findMaxScore(A, n));
}
}
 
// This code contributed by PrinciRaj1992

chevron_right


Output: 

13

 

Time complexity: O(N3)
 

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up

Recommended Posts:


Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.