📌  相关文章
📜  不相邻数组元素的最大可能总和不超过K

📅  最后修改于: 2021-05-06 21:22:11             🧑  作者: Mango

给定由N个整数和整数K组成的数组arr [] ,任务是选择一些最大可能和不超过K的相邻的数组元素

例子:

天真的方法:最简单的方法是递归生成给定数组的所有可能子集,对于每个子集,检查是否不包含相邻元素并且总和不超过K。在发现上述条件为真的所有子集中,打印任何子集获得的最大和。

下面是上述方法的实现:

C++
// C++ Program to implement
// the above approach
#include 
using namespace std;
 
// Function to find the
// maximum sum not exceeding
// K possible by selecting
// a subset of non-adjacent elements
int maxSum(int a[],
           int n, int k)
{
  // Base Case
  if (n <= 0)
    return 0;
 
  // Not selecting current
  // element
  int option = maxSum(a,
                      n - 1, k);
 
  // If selecting current
  // element is possible
  if (k >= a[n - 1])
    option = max(option,
                 a[n - 1] +
             maxSum(a, n - 2,
                    k - a[n - 1]));
 
  // Return answer
  return option;
}
 
// Driver Code
int main()
{
  // Given array arr[]
  int arr[] = {50, 10,
               20, 30, 40};
 
  int N = sizeof(arr) /
          sizeof(arr[0]);
 
  // Given K
  int K = 100;
 
  // Function Call
  cout << (maxSum(arr,
                  N, K));
}
 
// This code is contributed by gauravrajput1


Java
// Java program for the above approach
 
import java.io.*;
 
class GFG {
 
    // Function to find the maximum sum
    // not exceeding K possible by selecting
    // a subset of non-adjacent elements
    public static int maxSum(
        int a[], int n, int k)
    {
        // Base Case
        if (n <= 0)
            return 0;
 
        // Not selecting current element
        int option = maxSum(a, n - 1, k);
 
        // If selecting current element
        // is possible
        if (k >= a[n - 1])
            option = Math.max(
                option,
                a[n - 1]
                    + maxSum(a, n - 2,
                             k - a[n - 1]));
 
        // Return answer
        return option;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        // Given array arr[]
        int arr[] = { 50, 10, 20, 30, 40 };
 
        int N = arr.length;
 
        // Given K
        int K = 100;
 
        // Function Call
        System.out.println(maxSum(arr, N, K));
    }
}


Python3
# Python3 program for the above approach
 
# Function to find the maximum sum
# not exceeding K possible by selecting
# a subset of non-adjacent elements
def maxSum(a, n, k):
     
    # Base Case
    if (n <= 0):
        return 0
 
    # Not selecting current element
    option = maxSum(a, n - 1, k)
 
    # If selecting current element
    # is possible
    if (k >= a[n - 1]):
        option = max(option, a[n - 1] +
        maxSum(a, n - 2, k - a[n - 1]))
 
    # Return answer
    return option
 
# Driver Code
if __name__ == '__main__':
     
    # Given array arr[]
    arr = [ 50, 10, 20, 30, 40 ]
 
    N = len(arr)
 
    # Given K
    K = 100
 
    # Function Call
    print(maxSum(arr, N, K))
 
# This code is contributed by mohit kumar 29


C#
// C# program for the
// above approach
using System;
class GFG{
 
// Function to find the maximum
// sum not exceeding K possible
// by selecting a subset of
// non-adjacent elements
public static int maxSum(int []a,
                         int n, int k)
{
  // Base Case
  if (n <= 0)
    return 0;
 
  // Not selecting current element
  int option = maxSum(a, n - 1, k);
 
  // If selecting current
  // element is possible
  if (k >= a[n - 1])
    option = Math.Max(option, a[n - 1] +
                      maxSum(a, n - 2,
                             k - a[n - 1]));
   
  // Return answer
  return option;
}
 
// Driver Code
public static void Main(String[] args)
{
  // Given array []arr
  int []arr = {50, 10, 20, 30, 40};
 
  int N = arr.Length;
 
  // Given K
  int K = 100;
 
  // Function Call
  Console.WriteLine(maxSum(arr, N, K));
}
}
 
// This code is contributed by Rajput-Ji


C++
// C++ program for the above approach
#include 
using namespace std;
 
// Initialize dp
int dp[1005][1005];
 
// Function find the maximum sum that
// doesn't exceeds K by choosing elements
int maxSum(int* a, int n, int k)
{
     
    // Base Case
    if (n <= 0)
        return 0;
 
    // Return the memoized state
    if (dp[n][k] != -1)
        return dp[n][k];
 
    // Dont pick the current element
    int option = maxSum(a, n - 1, k);
 
    // Pick the current element
    if (k >= a[n - 1])
        option = max(option,
                     a[n - 1] +
             maxSum(a, n - 2,
                 k - a[n - 1]));
 
    // Return and store the result
    return dp[n][k] = option;
}
 
// Driver Code
int main()
{
    int N = 5;
 
    int arr[] = { 50, 10, 20, 30, 40 };
 
    int K = 100;
 
    // Fill dp array with -1
    memset(dp, -1, sizeof(dp));
 
    // Print answer
    cout << maxSum(arr, N, K) << endl;
}
 
// This code is contributed by bolliranadheer


Java
// Java program for the above approach
 
import java.util.*;
 
class GFG {
 
    // Function find the maximum sum that
    // doesn't exceeds K by choosing elements
    public static int maxSum(int a[], int n,
                             int k, int[][] dp)
    {
        // Base Case
        if (n <= 0)
            return 0;
 
        // Return the memoized state
        if (dp[n][k] != -1)
            return dp[n][k];
 
        // Dont pick the current element
        int option = maxSum(a, n - 1,
                            k, dp);
 
        // Pick the current element
        if (k >= a[n - 1])
            option = Math.max(
                option,
                a[n - 1]
                    + maxSum(a, n - 2,
                             k - a[n - 1],
                             dp));
 
        // Return and store the result
        return dp[n][k] = option;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        int arr[] = { 50, 10, 20, 30, 40 };
 
        int N = arr.length;
 
        int K = 100;
 
        // Initialize dp
        int dp[][] = new int[N + 1][K + 1];
 
        for (int i[] : dp) {
            Arrays.fill(i, -1);
        }
        // Print answer
        System.out.println(maxSum(arr, N, K, dp));
    }
}


Python3
# Python3 program for the
# above approach
 
# Function find the maximum
# sum that doesn't exceeds K
# by choosing elements
def maxSum(a, n, k, dp):
   
    # Base Case
    if (n <= 0):
        return 0;
 
    # Return the memoized state
    if (dp[n][k] != -1):
        return dp[n][k];
 
    # Dont pick the current
    # element
    option = maxSum(a, n - 1,
                    k, dp);
 
    # Pick the current element
    if (k >= a[n - 1]):
        option = max(option, a[n - 1] +
                 maxSum(a, n - 2,
                        k - a[n - 1], dp));
    dp[n][k] = option;
     
    # Return and store
    # the result
    return dp[n][k];
 
# Driver Code
if __name__ == '__main__':
   
    arr = [50, 10, 20,
           30, 40];
    N = len(arr);
    K = 100;
    # Initialize dp
    dp = [[-1 for i in range(K + 1)]
              for j in range(N + 1)]
 
    # Pranswer
    print(maxSum(arr, N,
                 K, dp));
 
# This code is contributed by shikhasingrajput


C#
// C# program for the
// above approach
using System;
class GFG{
 
// Function find the maximum
// sum that doesn't exceeds K
// by choosing elements
public static int maxSum(int []a, int n,
                         int k, int[,] dp)
{
  // Base Case
  if (n <= 0)
    return 0;
 
  // Return the memoized
  // state
  if (dp[n, k] != -1)
    return dp[n, k];
 
  // Dont pick the current
  // element
  int option = maxSum(a, n - 1,
                      k, dp);
 
  // Pick the current element
  if (k >= a[n - 1])
    option = Math.Max(option, a[n - 1] +
                      maxSum(a, n - 2,
                             k - a[n - 1],
                             dp));
 
  // Return and store the
  // result
  return dp[n, k] = option;
}
 
// Driver Code
public static void Main(String[] args)
{
  int []arr = {50, 10, 20, 30, 40};
  int N = arr.Length;
  int K = 100;
   
  // Initialize dp
  int [,]dp = new int[N + 1,
                      K + 1];
 
  for (int j = 0; j < N + 1; j++)
  {
    for (int k = 0; k < K + 1; k++)
      dp[j, k] = -1;
  }
   
  // Print answer
  Console.WriteLine(maxSum(arr, N,
                           K, dp));
}
}
 
// This code is contributed by Rajput-Ji


输出
90











时间复杂度: O(2 N )
辅助空间: O(N)

高效方法:为了优化上述方法,其思想是使用动态编程。每个数组元素都有两个可能的选项:

  1. 要么跳过当前元素,然后继续下一个元素。
  2. 仅当当前元素小于或等于K时,才选择它。

请按照以下步骤解决问题:

  1. -1初始化数组dp [N] [K + 1] ,其中dp [i] [j]将存储最大和以使用直到索引i的元素构成和j
  2. 从上面的转换中,递归地找到如果当前元素被选择以及如果当前元素未被选择的最大总和。
  3. 存储当前状态的最小答案。
  4. 另外,添加一个基本条件,即如果已经访问了当前状态(i,j),dp [i] [j]!=-1,则返回dp [i] [j]
  5. 打印dp [N] [K]作为最大可能的和。

下面是上述方法的实现:

C++

// C++ program for the above approach
#include 
using namespace std;
 
// Initialize dp
int dp[1005][1005];
 
// Function find the maximum sum that
// doesn't exceeds K by choosing elements
int maxSum(int* a, int n, int k)
{
     
    // Base Case
    if (n <= 0)
        return 0;
 
    // Return the memoized state
    if (dp[n][k] != -1)
        return dp[n][k];
 
    // Dont pick the current element
    int option = maxSum(a, n - 1, k);
 
    // Pick the current element
    if (k >= a[n - 1])
        option = max(option,
                     a[n - 1] +
             maxSum(a, n - 2,
                 k - a[n - 1]));
 
    // Return and store the result
    return dp[n][k] = option;
}
 
// Driver Code
int main()
{
    int N = 5;
 
    int arr[] = { 50, 10, 20, 30, 40 };
 
    int K = 100;
 
    // Fill dp array with -1
    memset(dp, -1, sizeof(dp));
 
    // Print answer
    cout << maxSum(arr, N, K) << endl;
}
 
// This code is contributed by bolliranadheer

Java

// Java program for the above approach
 
import java.util.*;
 
class GFG {
 
    // Function find the maximum sum that
    // doesn't exceeds K by choosing elements
    public static int maxSum(int a[], int n,
                             int k, int[][] dp)
    {
        // Base Case
        if (n <= 0)
            return 0;
 
        // Return the memoized state
        if (dp[n][k] != -1)
            return dp[n][k];
 
        // Dont pick the current element
        int option = maxSum(a, n - 1,
                            k, dp);
 
        // Pick the current element
        if (k >= a[n - 1])
            option = Math.max(
                option,
                a[n - 1]
                    + maxSum(a, n - 2,
                             k - a[n - 1],
                             dp));
 
        // Return and store the result
        return dp[n][k] = option;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        int arr[] = { 50, 10, 20, 30, 40 };
 
        int N = arr.length;
 
        int K = 100;
 
        // Initialize dp
        int dp[][] = new int[N + 1][K + 1];
 
        for (int i[] : dp) {
            Arrays.fill(i, -1);
        }
        // Print answer
        System.out.println(maxSum(arr, N, K, dp));
    }
}

Python3

# Python3 program for the
# above approach
 
# Function find the maximum
# sum that doesn't exceeds K
# by choosing elements
def maxSum(a, n, k, dp):
   
    # Base Case
    if (n <= 0):
        return 0;
 
    # Return the memoized state
    if (dp[n][k] != -1):
        return dp[n][k];
 
    # Dont pick the current
    # element
    option = maxSum(a, n - 1,
                    k, dp);
 
    # Pick the current element
    if (k >= a[n - 1]):
        option = max(option, a[n - 1] +
                 maxSum(a, n - 2,
                        k - a[n - 1], dp));
    dp[n][k] = option;
     
    # Return and store
    # the result
    return dp[n][k];
 
# Driver Code
if __name__ == '__main__':
   
    arr = [50, 10, 20,
           30, 40];
    N = len(arr);
    K = 100;
    # Initialize dp
    dp = [[-1 for i in range(K + 1)]
              for j in range(N + 1)]
 
    # Pranswer
    print(maxSum(arr, N,
                 K, dp));
 
# This code is contributed by shikhasingrajput

C#

// C# program for the
// above approach
using System;
class GFG{
 
// Function find the maximum
// sum that doesn't exceeds K
// by choosing elements
public static int maxSum(int []a, int n,
                         int k, int[,] dp)
{
  // Base Case
  if (n <= 0)
    return 0;
 
  // Return the memoized
  // state
  if (dp[n, k] != -1)
    return dp[n, k];
 
  // Dont pick the current
  // element
  int option = maxSum(a, n - 1,
                      k, dp);
 
  // Pick the current element
  if (k >= a[n - 1])
    option = Math.Max(option, a[n - 1] +
                      maxSum(a, n - 2,
                             k - a[n - 1],
                             dp));
 
  // Return and store the
  // result
  return dp[n, k] = option;
}
 
// Driver Code
public static void Main(String[] args)
{
  int []arr = {50, 10, 20, 30, 40};
  int N = arr.Length;
  int K = 100;
   
  // Initialize dp
  int [,]dp = new int[N + 1,
                      K + 1];
 
  for (int j = 0; j < N + 1; j++)
  {
    for (int k = 0; k < K + 1; k++)
      dp[j, k] = -1;
  }
   
  // Print answer
  Console.WriteLine(maxSum(arr, N,
                           K, dp));
}
}
 
// This code is contributed by Rajput-Ji
输出
90











时间复杂度: O(N * K),其中N是给定数组的大小,K是限制。
辅助空间: O(N)