Maximum score possible after performing given operations on an Array

02 Jun, 2021
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:  
If the operation is odd-numbered, the score is incremented by the sum of all elements of the current array.  If the operation is even-numbered, the score is decremented by the sum of all elements of the current array.  After every operation, either remove the first or the last element of the remaining array.  
If the operation is odd-numbered, the score is incremented by the sum of all elements of the current array.  
If the operation is even-numbered, the score is decremented by the sum of all elements of the current array.  
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  
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.  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, andThe current score.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:  
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.  
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, andThe current score.
The remaining array [l, r], where l represents the leftmost index and r the rightmost,
The operation number, and
The current score.
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]  
Below is the implementation of the above approach:  
C++
Java
Python3
C#
Javascript
// C++ program to find the maximum// score after given operations #include <bits/stdc++.h>using namespace std; // Function to calculate// maximum score recursivelyint 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 scoreint 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 codeint main(){    int n = 6;    int A[n] = { 1, 2, 3, 4, 2, 6 };     cout << findMaxScore(A, n);    return 0;}
// Java program to find the maximum// score after given operationsimport java.util.*; class GFG{ // Function to calculate// maximum score recursivelystatic 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 scorestatic 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 codepublic 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
# Python3 program to find the maximum# score after given operations # Function to calculate maximum# score recursivelydef 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 scoredef 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 coden = 6;A = [ 1, 2, 3, 4, 2, 6 ]ans = findMaxScore(A, n) print(ans) # This code is contributed by SoumikMondal
// C# program to find the maximum// score after given operationsusing System; class GFG{  // Function to calculate// maximum score recursivelystatic 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 scorestatic 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 codepublic 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
<script> // JavaScript program to find the maximum// score after given operations // Function to calculate// maximum score recursivelyfunction maxScore(l, r, prefix_sum, num){     // Base case    if (l > r)        return 0;     // Sum of array in range (l, r)    let 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 scorefunction findMaxScore(a, n){    // Prefix sum array    let prefix_sum = new Uint8Array(n);     prefix_sum[0] = a[0];     // Calculating prefix_sum    for (let i = 1; i < n; i++) {        prefix_sum[i]            = prefix_sum[i - 1] + a[i];    }     return maxScore(0, n - 1,                    prefix_sum, 1);} // Driver code     let n = 6;    let A = [ 1, 2, 3, 4, 2, 6 ];     document.write(findMaxScore(A, n));  // This code is contributed by Surbhi Tyagi. </script>
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++
Java
Python3
C#
Javascript
// C++ program to find the maximum// Score after given operations #include <bits/stdc++.h>using namespace std; // Memoizing by the use of a tableint dp[100][100][100]; // Function to calculate maximum scoreint 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 scoreint 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 codeint main(){    int n = 6;    int A[n] = { 1, 2, 3, 4, 2, 6 };     cout << findMaxScore(A, n);    return 0;}
// Java program to find the maximum// Score after given operations  class GFG{  // Memoizing by the use of a tablestatic int [][][]dp = new int[100][100][100];  // Function to calculate maximum scorestatic 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 scorestatic 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 codepublic 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
# python3 program to find the maximum# Score after given operations # Memoizing by the use of a tabledp = [[[-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 scoredef 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 codeif __name__ == "__main__":     n = 6    A = [1, 2, 3, 4, 2, 6]     print(findMaxScore(A, n))
// C# program to find the maximum// Score after given operations    using System; public class GFG{   // Memoizing by the use of a tablestatic int [,,]dp = new int[100,100,100];   // Function to calculate maximum scorestatic 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 scorestatic 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 codepublic 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
<script> // JavaScript program to find the maximum// Score after given operations // Memoizing by the use of a tablelet dp = new Array(100);// Initialising the DP table,    // -1 represents the subproblem    // hasn't been solved yetfor(let i=0;i<100;i++){    dp[i]=new Array(100);    for(let j=0;j<100;j++)    {        dp[i][j]=new Array(100);        for(let k=0;k<100;k++)        {            dp[i][j][k]=-1;        }    }} // Function to calculate maximum scorefunction 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)    let 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 scorefunction findMaxScore(a,n){    // Prefix sum array    let prefix_sum = new Array(n);       prefix_sum[0] = a[0];       // Calculating prefix_sum    for (let 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            return MaximumScoreDP(        0, n - 1,        prefix_sum, 1);} // Driver codelet n = 6;let A=[1, 2, 3, 4, 2, 6 ];document.write(findMaxScore(A, n));  // This code is contributed by rag2127 </script>
13
 
Time complexity: O(N3) 
sapnasingh4991
29AjayKumar
princiraj1992
SoumikMondal
ukasp
surbhityagi15
rag2127
Arrays
Dynamic Programming
Recursion
Arrays
Dynamic Programming
Recursion
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.