Open In App

Maximum sum such that exactly half of the elements are selected and no two adjacent

Last Updated : 03 Jun, 2021
Improve
Improve
Like Article
Like
Save
Share
Report

Given an array A containing N integers. Find the maximum sum possible such that exact floor(N/2) elements are selected and no two selected elements are adjacent to each other. (if N = 5, then exactly 2 elements should be selected as floor(5/2) = 2) 
For a simpler version of this problem check out this.

Examples:

Input: A = [1, 2, 3, 4, 5, 6] 
Output: 12 
Explanation: 
Select 2, 4 and 6 making the sum 12.

Input : A = [-1000, -100, -10, 0, 10] 
Output :
Explanation: 
Select -10 and 10, making the sum 0. 

Approach:  

  • We will use the concept of dynamic programming. The following is how the dp states are defined:

dp[i][j] = maximum sum till index i such that j elements are selected 

  • Since no two adjacent elements can be selected :

dp[i][j] = max(a[i] + dp[i-2][j-1], dp[i-1][j])  

Below is the implementation of the above approach. 

C++




// C++ program to find maximum sum possible
// such that exactly floor(N/2) elements
// are selected and no two selected
// elements are adjacent to each other
#include <bits/stdc++.h>
using namespace std;
 
// Function return the maximum sum
// possible under given condition
int MaximumSum(int a[], int n)
{
    int dp[n + 1][n + 1];
 
    // Intitialising the dp table
    for (int i = 0; i < n + 1; i++)
    {
        for (int j = 0; j < n + 1; j++)
            dp[i][j] = INT_MIN;
    }
 
    // Base case
    for (int i = 0; i < n + 1; i++)
        dp[i][0] = 0;
 
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= i; j++)
        {
            int val = INT_MIN;
 
            // Condition to select the current
            // element
            if ((i - 2 >= 0
                 && dp[i - 2][j - 1] != INT_MIN)
                                   || i - 2 < 0)
            {
                val = a[i - 1] +
                    (i - 2 >= 0 ?
                     dp[i - 2][j - 1] : 0);
            }
             
            // Condition to not select the
            // current element if possible
            if (i - 1 >= j)
            {
                val = max(val, dp[i - 1][j]);
            }
            dp[i][j] = val;
        }
    }
 
    return dp[n][n / 2];
}
 
//Driver code
int main()
{
     
    int A[] = {1, 2, 3, 4, 5, 6};
     
    int N = sizeof(A) / sizeof(A[0]);
 
    cout << MaximumSum(A, N);
 
    return 0;
}


Java




// Java program to find maximum sum possible
// such that exactly Math.floor(N/2) elements
// are selected and no two selected
// elements are adjacent to each other
class GFG{
 
// Function return the maximum sum
// possible under given condition
static int MaximumSum(int a[], int n)
{
    int [][]dp = new int[n + 1][n + 1];
 
    // Intitialising the dp table
    for(int i = 0; i < n + 1; i++)
    {
       for(int j = 0; j < n + 1; j++)
          dp[i][j] = Integer.MIN_VALUE;
    }
 
    // Base case
    for(int i = 0; i < n + 1; i++)
       dp[i][0] = 0;
 
    for(int i = 1; i <= n; i++)
    {
       for(int j = 1; j <= i; j++)
       {
          int val = Integer.MIN_VALUE;
           
          // Condition to select the current
          // element
          if ((i - 2 >= 0 &&
            dp[i - 2][j - 1] != Integer.MIN_VALUE) ||
               i - 2 < 0)
          {
              val = a[i - 1] + (i - 2 >= 0 ?
                             dp[i - 2][j - 1] : 0);
          }
           
          // Condition to not select the
          // current element if possible
          if (i - 1 >= j)
          {
              val = Math.max(val, dp[i - 1][j]);
          }
          dp[i][j] = val;
        }
    }
    return dp[n][n / 2];
}
 
// Driver code
public static void main(String[] args)
{
    int A[] = { 1, 2, 3, 4, 5, 6 };
    int N = A.length;
 
    System.out.print(MaximumSum(A, N));
}
}
 
// This code is contributed by Rajput-Ji


Python3




# Python3 program to find maximum sum possible
# such that exactly floor(N/2) elements
# are selected and no two selected
# elements are adjacent to each other
 
import sys
# Function return the maximum sum
# possible under given condition
def MaximumSum(a,n):
    dp = [[0 for i in range(n+1)] for j in range(n+1)]
 
    # Intitialising the dp table
    for i in range(n + 1):
        for j in range(n + 1):
            dp[i][j] = -sys.maxsize-1
 
    # Base case
    for i in range(n+1):
        dp[i][0] = 0
 
    for i in range(1,n+1,1):
        for j in range(1,i+1,1):
            val = -sys.maxsize-1
 
            # Condition to select the current
            # element
            if ((i - 2 >= 0 and dp[i - 2][j - 1] != -sys.maxsize-1) or i - 2 < 0):
                if (i - 2 >= 0):
                    val = a[i - 1] + dp[i - 2][j - 1]
                else:
                    val = a[i - 1]
             
            # Condition to not select the
            # current element if possible
            if (i - 1 >= j):
                val = max(val, dp[i - 1][j])
             
            dp[i][j] = val
 
    return dp[n][n // 2]
 
#Driver code
if __name__ == '__main__':
    A = [1, 2, 3, 4, 5, 6]
     
    N = len(A)
 
    print(MaximumSum(A,N))
 
# This code is contributed by Bhupendra_Singh


C#




// C# program to find maximum sum possible
// such that exactly Math.floor(N/2) elements
// are selected and no two selected
// elements are adjacent to each other
using System;
 
class GFG{
 
// Function return the maximum sum
// possible under given condition
static int MaximumSum(int []a, int n)
{
    int [,]dp = new int[n + 1, n + 1];
 
    // Intitialising the dp table
    for(int i = 0; i < n + 1; i++)
    {
       for(int j = 0; j < n + 1; j++)
          dp[i, j] = Int32.MinValue;
    }
 
    // Base case
    for(int i = 0; i < n + 1; i++)
       dp[i, 0] = 0;
 
    for(int i = 1; i <= n; i++)
    {
       for(int j = 1; j <= i; j++)
       {
          int val = Int32.MinValue;
           
          // Condition to select the current
          // element
          if ((i - 2 >= 0 &&
            dp[i - 2, j - 1] != Int32.MinValue) ||
               i - 2 < 0)
          {
              val = a[i - 1] + (i - 2 >= 0 ?
                             dp[i - 2, j - 1] : 0);
          }
           
          // Condition to not select the
          // current element if possible
          if (i - 1 >= j)
          {
              val = Math.Max(val, dp[i - 1, j]);
          }
          dp[i, j] = val;
       }
    }
    return dp[n, n / 2];
}
 
// Driver code
public static void Main()
{
    int []A = { 1, 2, 3, 4, 5, 6 };
    int N = A.Length;
 
    Console.Write(MaximumSum(A, N));
}
}
 
// This code is contributed by Nidhi_biet


Javascript




<script>
 
// JavaScript program to find maximum sum possible
// such that exactly Math.floor(N/2) elements
// are selected and no two selected
// elements are adjacent to each other
 
 
// Function return the maximum sum
// possible under given condition
function MaximumSum(a,n)
{
    let dp = [];
 
    for(let i=0;i<n+1;i++) dp.push(Array(n+1));
 
    // Intitialising the dp table
    for(let i = 0; i < n + 1; i++)
    {
       for(let j = 0; j < n + 1; j++)
          dp[i][j] = -10000;
    }
 
    // Base case
    for(let i = 0; i < n + 1; i++)
       dp[i][0] = 0;
 
    for(let i = 1; i <= n; i++)
    {
       for(let j = 1; j <= i; j++)
       {
          let val = -10000;
           
          // Condition to select the current
          // element
          if ((i - 2 >= 0 &&
            dp[i - 2, j - 1] != -10000) ||
               i - 2 < 0)
          {
              val = a[i - 1] + (i - 2 >= 0 ?
                             dp[i - 2][j - 1] : 0);
          }
           
          // Condition to not select the
          // current element if possible
          if (i - 1 >= j)
          {
              val = Math.max(val, dp[i - 1][j]);
          }
          dp[i][j] = val;
       }
    }
    return dp[n][n / 2]
}
 
// Driver code
 
let A = [1, 2, 3, 4, 5, 6];
let N = A.length;
 
document.write(MaximumSum(A, N));
 
// This code is contributed by Nidhi_biet
 
</script>


Output: 

12

 

Time Complexity : O(N2)
 

Efficient Approach  

  • We will use dynamic programming but with slightly modified states. Storing both the index and is number of elements taken till now are futile since we always need to take exact floor(i/2) elements, so at i’th position for the dp storage we will assume floor(i/2) elements in the subset till now.
  • The following is the dp table states:

dp[i][1] = maximum sum till i’th index, picking element a[i], with floor(i/2) elements, none adjacent to each other. 
dp[i][0] = maximum sum till i’th index, not picking element a[i], with floor(i/2) elements, none adjacent to each other. 

  • We have two cases : 
    • When i is odd : If we have to pick a[i], then we can’t pick a[i-1], so the only options left are (i – 2)th and (i – 3) rd state (because floor((i – 2)/2) = floor((i – 3)/2) = floor(i/2) – 1, and since we pick a[i], total picked elements will be floor(i/2) ). If we don’t pick a[i], then a sum will be formed by taking a[i-1] and using states i – 1, i – 2 and i – 3 or a[i – 2] using state i – 3 as these will only give the total of floor(i/2).

dp[i][1] = arr[i] + max({dp[i – 3][1], dp[i – 3][0], dp[i – 2][1], dp[i – 2][0]}) 
dp[i][0] = max({arr[i – 1] + dp[i – 2][0], arr[i – 1] + dp[i – 3][1], arr[i – 1] + dp[i – 3][0], 
arr[i – 2] + dp[i – 3][0]})  

  • When i is even : If we pick a[i], then using states i – 1 and i – 2, else picking a[i – 1] and using state i – 2. 
     

dp[i][1] = arr[i] + max({dp[i – 2][1], dp[i – 2][0], dp[i – 1][0]}) 
dp[i][0] = arr[i – 1] + dp[i – 2][0] 

Below is the implementation of the above approach.  

C++




// C++ program to find maximum sum possible
// such that exactly floor(N/2) elements
// are selected and no two selected
// elements are adjacent to each other
#include <bits/stdc++.h>
using namespace std;
 
// Function return the maximum sum
// possible under given condition
int MaximumSum(int a[], int n)
{
 
    int dp[n + 1][2];
     
    // Intitialising the dp table
    memset(dp, 0, sizeof(dp));
 
    // Base case
    dp[2][1] = a[1];
    dp[2][0] = a[0];
 
    for (int i = 3; i < n + 1; i++) {
        // When i is odd
        if (i & 1) {
            int temp = max({ dp[i - 3][1],
                             dp[i - 3][0],
                             dp[i - 2][1],
                             dp[i - 2][0] });
             
            dp[i][1] = a[i - 1] + temp;
            dp[i][0] = max({ a[i - 2] + dp[i - 2][0],
                             a[i - 2] + dp[i - 3][1],
                             a[i - 2] + dp[i - 3][0],
                             a[i - 3] + dp[i - 3][0] });
        }
 
        // When i is even
        else {
            dp[i][1] = a[i - 1] + max({ dp[i - 2][1],
                                        dp[i - 2][0],
                                        dp[i - 1][0] });
             
            dp[i][0] = a[i - 2] + dp[i - 2][0];
        }
    }
    // Maximum of if we pick last element or not
    return max(dp[n][1], dp[n][0]);
}
 
// Driver code
int main()
{
    int A[] = {1, 2, 3, 4, 5, 6};
     
    int N = sizeof(A) / sizeof(A[0]);
 
    cout << MaximumSum(A, N);
 
    return 0;
}


Java




// Java program to find maximum sum possible
// such that exactly Math.floor(N/2) elements
// are selected and no two selected
// elements are adjacent to each other
import java.util.*;
 
class GFG{
 
// Function return the maximum sum
// possible under given condition
static int MaximumSum(int a[], int n)
{
 
    int [][]dp = new int[n + 1][2];
 
    // Base case
    dp[2][1] = a[1];
    dp[2][0] = a[0];
 
    for(int i = 3; i < n + 1; i++)
    {
        
       // When i is odd
       if (i % 2 == 1)
       {
           int temp = Math.max((Math.max(dp[i - 3][1],
                                         dp[i - 3][0])),
                                Math.max(dp[i - 2][1],
                                         dp[i - 2][0]));
           dp[i][1] = a[i - 1] + temp;
           dp[i][0] = Math.max((Math.max(a[i - 2] +
                                        dp[i - 2][0],
                                         a[i - 2] +
                                        dp[i - 3][1])),
                                Math.max(a[i - 2] +
                                        dp[i - 3][0],
                                         a[i - 3] +
                                        dp[i - 3][0]));
       }
        
       // When i is even
       else
       {
           dp[i][1] = a[i - 1] + (Math.max((
                                  Math.max(dp[i - 2][1],
                                           dp[i - 2][0])),
                                           dp[i - 1][0]));
           dp[i][0] = a[i - 2] + dp[i - 2][0];
       }
    }
     
    // Maximum of if we pick last element or not
    return Math.max(dp[n][1], dp[n][0]);
}
 
static int max(int []arr)
{
    return 1;
}
 
// Driver code
public static void main(String[] args)
{
    int A[] = {1, 2, 3, 4, 5, 6};
    int N = A.length;
 
    System.out.print(MaximumSum(A, N));
}
}
 
// This code is contributed by Rajput-Ji


Python3




# Python3 program to find maximum sum possible
# such that exactly floor(N/2) elements
# are selected and no two selected
# elements are adjacent to each other
 
# Function return the maximum sum
# possible under given condition
def MaximumSum(a, n):
 
    dp = [[0 for x in range (2)]
             for y in range(n + 1)]
     
    # Base case
    dp[2][1] = a[1]
    dp[2][0] = a[0]
 
    for i in range (3, n + 1):
       
        # When i is odd
        if (i & 1):
            temp = max([dp[i - 3][1],
                        dp[i - 3][0],
                        dp[i - 2][1],
                        dp[i - 2][0]])
             
            dp[i][1] = a[i - 1] + temp
            dp[i][0] = max([a[i - 2] + dp[i - 2][0],
                            a[i - 2] + dp[i - 3][1],
                            a[i - 2] + dp[i - 3][0],
                            a[i - 3] + dp[i - 3][0]])
 
        # When i is even
        else:
            dp[i][1] = (a[i - 1] + max([dp[i - 2][1],
                                        dp[i - 2][0],
                                        dp[i - 1][0]]))
             
            dp[i][0] = a[i - 2] + dp[i - 2][0]
       
    # Maximum of if we pick last
    # element or not
    return max(dp[n][1], dp[n][0])
 
# Driver code
if __name__ == "__main__"
   
    A = [1, 2, 3, 4, 5, 6]   
    N = len(A)
    print(MaximumSum(A, N))
 
# This code is contributed by Chitranayal


C#




// C# program to find maximum sum possible
// such that exactly Math.Floor(N/2) elements
// are selected and no two selected
// elements are adjacent to each other
using System;
 
class GFG{
 
// Function return the maximum sum
// possible under given condition
static int MaximumSum(int []a, int n)
{
    int [,]dp = new int[n + 1, 2];
 
    // Base case
    dp[2, 1] = a[1];
    dp[2, 0] = a[0];
 
    for(int i = 3; i < n + 1; i++)
    {
 
       // When i is odd
       if (i % 2 == 1)
       {
           int temp = Math.Max((Math.Max(dp[i - 3, 1],
                                         dp[i - 3, 0])),
                                Math.Max(dp[i - 2, 1],
                                         dp[i - 2, 0]));
           dp[i, 1] = a[i - 1] + temp;
           dp[i, 0] = Math.Max((Math.Max(a[i - 2] +
                                        dp[i - 2, 0],
                                         a[i - 2] +
                                        dp[i - 3, 1])),
                                Math.Max(a[i - 2] +
                                        dp[i - 3, 0],
                                         a[i - 3] +
                                        dp[i - 3, 0]));
       }
        
       // When i is even
       else
       {
           dp[i, 1] = a[i - 1] + (Math.Max((
                                  Math.Max(dp[i - 2, 1],
                                           dp[i - 2, 0])),
                                           dp[i - 1, 0]));
           dp[i, 0] = a[i - 2] + dp[i - 2, 0];
       }
    }
     
    // Maximum of if we pick last element or not
    return Math.Max(dp[n, 1], dp[n, 0]);
}
 
static int max(int []arr)
{
    return 1;
}
 
// Driver code
public static void Main(String[] args)
{
    int []A = { 1, 2, 3, 4, 5, 6 };
    int N = A.Length;
 
    Console.Write(MaximumSum(A, N));
}
}
 
// This code is contributed by 29AjayKumar


Javascript




<script>
 
// Javascript program to find maximum sum possible
// such that exactly floor(N/2) elements
// are selected and no two selected
// elements are adjacent to each other
 
// Function return the maximum sum
// possible under given condition
function MaximumSum(a, n)
{
 
    var dp = Array.from(Array(n+1), ()=>Array(2).fill(0));
 
    // Base case
    dp[2][1] = a[1];
    dp[2][0] = a[0];
 
    for (var i = 3; i < n + 1; i++) {
        // When i is odd
        if (i & 1) {
            var temp = ([dp[i - 3][1],
                             dp[i - 3][0],
                             dp[i - 2][1],
                             dp[i - 2][0] ].reduce((a,b)=>
                               Math.max(a,b)));
             
            dp[i][1] = a[i - 1] + temp;
            dp[i][0] = ([ a[i - 2] + dp[i - 2][0],
                             a[i - 2] + dp[i - 3][1],
                             a[i - 2] + dp[i - 3][0],
                             a[i - 3] + dp[i - 3][0] ].reduce((a,b)=>
                               Math.max(a,b)));
        }
 
        // When i is even
        else {
            dp[i][1] = a[i - 1] + ([ dp[i - 2][1],
                                        dp[i - 2][0],
                                        dp[i - 1][0] ].reduce((a,b)=>
                                          Math.max(a,b)));
             
            dp[i][0] = a[i - 2] + dp[i - 2][0];
        }
    }
    // Maximum of if we pick last element or not
    return Math.max(dp[n][1], dp[n][0]);
}
 
// Driver code
var A = [1, 2, 3, 4, 5, 6];
 
var N = A.length;
document.write( MaximumSum(A, N));
 
 
</script>


Output: 

12

 

Time Complexity: O(N)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads