📌  相关文章
📜  最大总和,使得恰好选择了一半的元素,并且没有两个相邻的元素

📅  最后修改于: 2021-05-13 23:20:39             🧑  作者: Mango

给定一个包含N个整数的数组A。找到最大可能的总和,以使恰好选择了floor(N / 2)个元素,并且没有两个选定的元素彼此相邻。 (如果N = 5,则应精确选择2个元素作为floor(5/2)= 2)
有关此问题的更简单版本,请查看此内容。
例子:

方法:

  • 我们将使用动态编程的概念。以下是dp状态的定义方式:
  • 由于不能选择两个相邻的元素:

下面是上述方法的实现。

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 
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


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 
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


输出:
12



时间复杂度: O(N 2 )
高效方法

  • 我们将使用动态编程,但状态要稍加修改。由于我们始终需要精确地获取floor(i / 2)个元素,因此存储到目前为止获取的元素的索引和数量都是徒劳的,因此在dp存储的第i个位置,我们将假设第一个元素中的floor(i / 2)个元素子集到现在为止。
  • 以下是dp表状态:
  • 我们有两种情况:
    • 当i为奇数时:如果我们选择a [i],那么我们就不能选择a [i-1],因此剩下的唯一选项是第(i – 2)个和第(i – 3)个状态(因为floor( (i – 2)/ 2)= floor((i – 3)/ 2)= floor(i / 2)– 1,由于我们选取a [i],所以拾取的元素总数为floor(i / 2)) 。如果我们不选择a [i],那么将通过取a [i-1]并使用状态i – 1,i – 2和i – 3或a [i – 2]使用状态i – 3来形成和。因为这些仅将得出楼底的总和(i / 2)。
  • 当我是偶数时:如果我们选择a [i],则使用状态i – 1和i – 2,否则选择a [i – 1]并使用状态i – 2。

下面是上述方法的实现。

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 
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
输出:
12



时间复杂度: O(N)