给定一个包含 N 个整数的数组 A。找到可能的最大总和,以便选择精确的 floor(N/2) 个元素并且没有两个选定的元素彼此相邻。 (如果 N = 5,则应选择 2 个元素作为 floor(5/2) = 2)
有关此问题的更简单版本,请查看此内容。
例子:
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 : 0
Explanation:
Select -10 and 10, making the sum 0.
方法:
- 我们将使用动态规划的概念。以下是 dp 状态的定义方式:
dp[i][j] = maximum sum till index i such that j elements are selected
- 由于不能选择两个相邻的元素:
dp[i][j] = max(a[i] + dp[i-2][j-1], dp[i-1][j])
下面是上述方法的实现。
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
Javascript
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
Javascript
12
时间复杂度: O(N 2 )
有效的方法
- 我们将使用动态规划,但会稍微修改状态。存储索引和元素的数量直到现在都是徒劳的,因为我们总是需要获取精确的 floor(i/2) 个元素,所以在 dp 存储的第 i 个位置我们将假设 floor(i/2) 个元素在子集到现在。
- 以下是 dp 表状态:
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.
- 我们有两种情况:
- 当 i 是奇数时:如果我们必须选择 a[i],那么我们不能选择 a[i-1],所以剩下的唯一选项是 (i – 2)th 和 (i – 3) rd state(因为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 因为这些只会给出 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]})
- 当 i 是偶数时:如果我们选择 a[i],则使用状态 i-1 和 i-2,否则选择 a[i-1] 并使用状态 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]
下面是上述方法的实现。
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
蟒蛇3
# 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
12
时间复杂度: O(N)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。