Maximize the subarray sum after multiplying all elements of any subarray with X

Given an array arr[] of N integers and an integer X. We can choose any sub-array and multiply all its element by X. After multiplication, find the sub-array with the maximum sum. The task is to multiply the sub-array in such a way that the final sub-array sum is maximized.

Examples:

Input: arr[] = { -3, 8, -2, 1, -6 }, X = -1
Output: 15
Choose the sub-array with {-2, 1, -6} and multiply X.
Now the new array is {-3, 8, 2, -1, 6} whose maximum sub-array sum is 15.

Input: arr[] = {1, 2, 4, -10}, X = 2
Output: 14

Approach: The problem cannot be solved using a greedy approach. Greedy approach fails in many cases one of them being a[] = { -3, 8, -2, 1, 6 } and x = -1. We will use Dynamic Programming to solve the above problem. Let dp[ind][state], where ind is the current index in the array and there are 3 states.

  • The first state defines that no sub-array has been chosen till index ind to be multiplied with X.
  • The second state defines that the current element at index ind is in the sub-array which is multiplied with X.
  • The third state defines that the sub-array has already been chosen.

Kadane’s algorithm has been used along with DP to get the maximum subarray sum simultaneously.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
#define N 5
  
// Function to return the maximum sum
int func(int idx, int cur, int a[], int dp[N][3], int n, int x)
{
  
    // Base case
    if (idx == n)
        return 0;
  
    // If already calculated
    if (dp[idx][cur] != -1)
        return dp[idx][cur];
  
    int ans = 0;
  
    // If no elements have been chosen
    if (cur == 0) {
  
        // Do not choose any element and use
        // Kadane's algorithm by taking max
        ans = max(ans, a[idx] + func(idx + 1, 0, a, dp, n, x));
  
        // Choose the sub-array and multiply x
        ans = max(ans, x * a[idx] + func(idx + 1, 1, a, dp, n, x));
    }
    else if (cur == 1) {
  
        // Choose the sub-array and multiply x
        ans = max(ans, x * a[idx] + func(idx + 1, 1, a, dp, n, x));
  
        // End the sub-array multiplication
        ans = max(ans, a[idx] + func(idx + 1, 2, a, dp, n, x));
    }
    else
  
        // No more multiplication
        ans = max(ans, a[idx] + func(idx + 1, 2, a, dp, n, x));
  
    // Memoize and return the answer
    return dp[idx][cur] = ans;
}
  
// Function to get the maximum sum
int getMaximumSum(int a[], int n, int x)
{
  
    // Initialize dp with -1
    int dp[n][3];
    memset(dp, -1, sizeof dp);
  
    // Iterate from every position and find the
    // maximum sum which is possible
    int maxi = 0;
    for (int i = 0; i < n; i++)
        maxi = max(maxi, func(i, 0, a, dp, n, x));
  
    return maxi;
}
  
// Driver code
int main()
{
    int a[] = { -3, 8, -2, 1, -6 };
    int n = sizeof(a) / sizeof(a[0]);
    int x = -1;
  
    cout << getMaximumSum(a, n, x);
  
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java implementation of the approach
class GFG
{
  
    static int N = 5;
  
// Function to return the maximum sum
static int func(int idx, int cur, int a[],
                int dp[][], int n, int x)
{
  
    // Base case
    if (idx == n)
    {
        return 0;
    }
  
    // If already calculated
    if (dp[idx][cur] != -1)
    {
        return dp[idx][cur];
    }
  
    int ans = 0;
  
    // If no elements have been chosen
    if (cur == 0)
    {
  
        // Do not choose any element and use
        // Kadane's algorithm by taking max
        ans = Math.max(ans, a[idx] + 
                func(idx + 1, 0, a, dp, n, x));
  
        // Choose the sub-array and multiply x
        ans = Math.max(ans, x * a[idx] + 
                func(idx + 1, 1, a, dp, n, x));
    
    else if (cur == 1)
    {
  
        // Choose the sub-array and multiply x
        ans = Math.max(ans, x * a[idx] + 
                func(idx + 1, 1, a, dp, n, x));
  
        // End the sub-array multiplication
        ans = Math.max(ans, a[idx] + 
                func(idx + 1, 2, a, dp, n, x));
    
    else // No more multiplication
    {
        ans = Math.max(ans, a[idx] + 
                func(idx + 1, 2, a, dp, n, x));
    }
  
    // Memoize and return the answer
    return dp[idx][cur] = ans;
}
  
// Function to get the maximum sum
static int getMaximumSum(int a[], int n, int x)
{
  
    // Initialize dp with -1
    int dp[][] = new int[n][3];
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            dp[i][j] = -1;
        }
    }
  
    // Iterate from every position and find the
    // maximum sum which is possible
    int maxi = 0;
    for (int i = 0; i < n; i++)
    {
        maxi = Math.max(maxi, func(i, 0, a, dp, n, x));
    }
  
    return maxi;
}
  
// Driver code
public static void main(String[] args) 
{
    int a[] = {-3, 8, -2, 1, -6};
    int n = a.length;
    int x = -1;
    System.out.println(getMaximumSum(a, n, x));
  
}
}
  
// This code has been contributed by 29AjayKumar

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 implementation of the approach
  
N = 5
  
# Function to return the maximum sum
def func(idx, cur, a, dp, n, x) :
   
  
    # Base case
    if (idx == n) :
        return 0 
  
    # If already calculated
    if (dp[idx][cur] != -1):
        return dp[idx][cur] 
  
    ans = 0 
  
    # If no elements have been chosen
    if (cur == 0) :
  
        # Do not choose any element and use
        # Kadane's algorithm by taking max
        ans = max(ans, a[idx] + func(idx + 1, 0, a, dp, n, x)) 
  
        # Choose the sub-array and multiply x
        ans = max(ans, x * a[idx] + func(idx + 1, 1, a, dp, n, x)) 
       
    elif (cur == 1) :
  
        # Choose the sub-array and multiply x
        ans = max(ans, x * a[idx] + func(idx + 1, 1, a, dp, n, x)) 
  
        # End the sub-array multiplication
        ans = max(ans, a[idx] + func(idx + 1, 2, a, dp, n, x)) 
       
    else :
  
        # No more multiplication
        ans = max(ans, a[idx] + func(idx + 1, 2, a, dp, n, x)) 
  
    # Memoize and return the answer
    dp[idx][cur] = ans 
      
    return dp[idx][cur]
   
  
# Function to get the maximum sum
def getMaximumSum(a, n, x) :
   
  
    # Initialize dp with -1
    dp = [[-1 for i in range(3)] for j in range(n)]
      
  
    # Iterate from every position and find the
    # maximum sum which is possible
    maxi = 0 
    for i in range (0, n) :
        maxi = max(maxi, func(i, 0, a, dp, n, x)) 
  
    return maxi 
   
  
# Driver code
  
a =  [ -3, 8, -2, 1, -6 ]   
n = len(a) 
x = -1 
  
print(getMaximumSum(a, n, x)) 
  
# This code is contributed by ihritik

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# implementation of the approach
using System;
  
class GFG
{
  
    static int N = 5;
  
// Function to return the maximum sum
static int func(int idx, int cur, int []a,
                int [,]dp, int n, int x)
{
  
    // Base case
    if (idx == n)
    {
        return 0;
    }
  
    // If already calculated
    if (dp[idx,cur] != -1)
    {
        return dp[idx,cur];
    }
  
    int ans = 0;
  
    // If no elements have been chosen
    if (cur == 0)
    {
  
        // Do not choose any element and use
        // Kadane's algorithm by taking max
        ans = Math.Max(ans, a[idx] + 
                func(idx + 1, 0, a, dp, n, x));
  
        // Choose the sub-array and multiply x
        ans = Math.Max(ans, x * a[idx] + 
                func(idx + 1, 1, a, dp, n, x));
    
    else if (cur == 1)
    {
  
        // Choose the sub-array and multiply x
        ans = Math.Max(ans, x * a[idx] + 
                func(idx + 1, 1, a, dp, n, x));
  
        // End the sub-array multiplication
        ans = Math.Max(ans, a[idx] + 
                func(idx + 1, 2, a, dp, n, x));
    
    else // No more multiplication
    {
        ans = Math.Max(ans, a[idx] + 
                func(idx + 1, 2, a, dp, n, x));
    }
  
    // Memoize and return the answer
    return dp[idx,cur] = ans;
}
  
// Function to get the maximum sum
static int getMaximumSum(int []a, int n, int x)
{
  
    // Initialize dp with -1
    int [,]dp = new int[n,3];
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            dp[i,j] = -1;
        }
    }
  
    // Iterate from every position and find the
    // maximum sum which is possible
    int maxi = 0;
    for (int i = 0; i < n; i++)
    {
        maxi = Math.Max(maxi, func(i, 0, a, dp, n, x));
    }
  
    return maxi;
}
  
// Driver code
public static void Main(String[] args) 
{
    int []a = {-3, 8, -2, 1, -6};
    int n = a.Length;
    int x = -1;
    Console.WriteLine(getMaximumSum(a, n, x));
  
}
}
  
/* This code contributed by PrinciRaj1992 */

chevron_right


PHP

filter_none

edit
close

play_arrow

link
brightness_4
code

<?php
// PHP implementation of the approach 
  
$N = 5; 
  
// Function to return the maximum sum 
function func($idx, $cur, $a, $dp, $n, $x
  
    // Base case 
    if ($idx == $n
        return 0; 
  
    // If already calculated 
    if ($dp[$idx][$cur] != -1) 
        return $dp[$idx][$cur]; 
  
    $ans = 0; 
  
    // If no elements have been chosen 
    if ($cur == 0) 
    
  
        // Do not choose any element and use 
        // Kadane's algorithm by taking max 
        $ans = max($ans, $a[$idx] + 
                func($idx + 1, 0, $a, $dp, $n, $x)); 
  
        // Choose the sub-array and multiply x 
        $ans = max($ans, $x * $a[$idx] + 
                func($idx + 1, 1, $a, $dp, $n, $x)); 
    
    else if ($cur == 1)
    
  
        // Choose the sub-array and multiply x 
        $ans = max($ans, $x * $a[$idx] + 
                func($idx + 1, 1, $a, $dp, $n, $x)); 
  
        // End the sub-array multiplication 
        $ans = max($ans, $a[$idx] + 
                func($idx + 1, 2, $a, $dp, $n, $x)); 
    
    else
  
        // No more multiplication 
        $ans = max($ans, $a[$idx] + 
                func($idx + 1, 2, $a, $dp,$n, $x)); 
  
    // Memoize and return the answer 
    return $dp[$idx][$cur] = $ans
  
// Function to get the maximum sum 
function getMaximumSum($a, $n, $x
  
    // Initialize dp with -1 
    $dp = array(array()) ;
      
    for($i = 0; $i < $n; $i++)
    {
        for($j = 0; $j < 3; $j++)
        {
            $dp[$i][$j] = -1;
        }
    }
  
    // Iterate from every position and find the 
    // maximum sum which is possible 
    $maxi = 0; 
    for ($i = 0; $i < $n; $i++) 
        $maxi = max($maxi, func($i, 0, $a, $dp, $n, $x)); 
  
    return $maxi
  
    // Driver code 
    $a = array( -3, 8, -2, 1, -6 ); 
    $n = count($a) ;
    $x = -1; 
  
    echo getMaximumSum($a, $n, $x); 
      
    // This code is contributed by Ryuga
?>

chevron_right


Output:

15

Time Complexity: O(N * 3)
Auxiliary Space: O(N * 3)



My Personal Notes arrow_drop_up

Striver(underscore)79 at Codechef and codeforces D

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.