📌  相关文章
📜  通过从给定数组中获取最多 K 个元素,找到可被 D 整除的最大子集和

📅  最后修改于: 2021-09-22 10:22:12             🧑  作者: Mango

给定大小为N的数组A[]和两个数字KD ,任务是通过从A 中取出最多K 个元素来计算可能被D整除的最大子集和。

例子:

朴素的方法:朴素的方法是生成A 的所有子集(使用位掩码),并对每个子集计算总和,并检查子集的长度是否不大于K ,总和是否可以被D整除,并计算其中的最大值。

下面是上述方法的实现:

C++
// C++ program for tha above approach
#include 
using namespace std;
 
// Function to calculate maximum sum possible by taking at
// most K elements that is divisibly by D
int maximumSum(vector A, int N, int K, int D)
{
    // variable to store final answer
    int ans = 0;
    // Traverse all subsets
    for (int i = 0; i < (1 << N); i++) {
        int sum = 0;
        int c = 0;
        for (int j = 0; j < N; j++) {
            if (i >> j & 1) {
                sum += A[j];
                c++;
            }
        }
        // Update ans if necessary
        // conditions are satisfied
        if (sum % D == 0 && c <= K)
            ans = max(ans, sum);
    }
    return ans;
}
// Driver code
int main()
{
    // Input
    int N = 5, K = 3, D = 7;
    vector A = { 1, 11, 5, 5, 18 };
 
    // Function call
    cout << maximumSum(A, N, K, D) << endl;
 
    return 0;
}


Java
// Java program for tha above approach
import java.util.*;
 
class GFG{
 
// Function to calculate maximum sum
// possible by taking at most K
// elements that is divisibly by D
static int maximumSum(int[] A, int N,
                      int K, int D)
{
     
    // Variable to store final answer
    int ans = 0;
     
    // Traverse all subsets
    for(int i = 0; i < (1 << N); i++)
    {
        int sum = 0;
        int c = 0;
        for(int j = 0; j < N; j++)
        {
            if ((i >> j & 1) != 0)
            {
                sum += A[j];
                c++;
            }
        }
         
        // Update ans if necessary
        // conditions are satisfied
        if (sum % D == 0 && c <= K)
            ans = Math.max(ans, sum);
    }
    return ans;
}
 
// Driver Code
public static void main(String[] args)
{
     
    // Input
    int N = 5, K = 3, D = 7;
    int[] A = { 1, 11, 5, 5, 18 };
 
    // Function call
    System.out.print(maximumSum(A, N, K, D));
}   
}
 
// This code is contributed by susmitakundugoaldanga


Python3
# Python3 program for tha above approach
 
# Function to calculate maximum sum
# possible by taking at most K elements
# that is divisibly by D
def maximumSum(A, N, K, D):
     
    # Variable to store final answer
    ans = 0
     
    # Traverse all subsets
    for i in range((1 << N)):
        sum = 0
        c = 0
         
        for j in range(N):
            if (i >> j & 1):
                sum += A[j]
                c += 1
                 
        # Update ans if necessary
        # conditions are satisfied
        if (sum % D == 0 and c <= K):
            ans = max(ans, sum)
             
    return ans
 
# Driver code
if __name__ == '__main__':
     
    # Input
    N = 5
    K = 3
    D = 7
    A = [ 1, 11, 5, 5, 18 ]
 
    # Function call
    print(maximumSum(A, N, K, D))
 
# This code is contributed by mohit kumar 29


C#
// C# program for tha above approach
using System;
using System.Collections.Generic;
 
class GFG{
  
// Function to calculate maximum sum possible
// by taking at most K elements that is divisibly by D
static int maximumSum(List A, int N,
                           int K, int D)
{
     
    // Variable to store final answer
    int ans = 0;
     
    // Traverse all subsets
    for(int i = 0; i < (1 << N); i++)
    {
        int sum = 0;
        int c = 0;
        for(int j = 0; j < N; j++)
        {
            if ((i >> j & 1) != 0)
            {
                sum += A[j];
                c++;
            }
        }
         
        // Update ans if necessary
        // conditions are satisfied
        if (sum % D == 0 && c <= K)
            ans = Math.Max(ans, sum);
    }
    return ans;
}
 
// Driver code
public static void Main()
{
     
    // Input
    int N = 5, K = 3, D = 7;
    List A = new List(){ 1, 11, 5, 5, 18 };
 
    // Function call
    Console.Write(maximumSum(A, N, K, D));
}
}
 
// This code is contributed by SURENDRA_GANGWAR


Javascript


C++
#include 
using namespace std;
int maximumSum(vector A, int N, int K, int D)
{
    // Dp vector
    vector > > dp(
        N + 1, vector >(
                   K + 1, vector(D + 1, -1)));
    for (int i = 1; i <= N; i++) {
        // current element
        int element = A[i - 1];
        // current element modulo D
        int mod = A[i - 1] % D;
        // copy previous state
        dp[i] = dp[i - 1];
        for (int j = 1; j <= K; j++) {
            // Transitions
            dp[i][j][mod] = max(dp[i][j][mod], element);
            for (int p = 0; p < D; p++) {
                if (dp[i - 1][j - 1][p] != -1) {
                    dp[i][j][(p + mod) % D] = max(
                        dp[i][j][(p + mod) % D],
                        dp[i - 1][j - 1][p] + element);
                }
            }
        }
    }
    // return answer
    if (dp[N][K][0] == -1)
        return 0;
    return dp[N][K][0];
}
// Driver code
int main()
{
    // Input
    int N = 5, K = 3, D = 7;
    vector A = { 1, 11, 5, 5, 18 };
 
    // Function call
    cout << maximumSum(A, N, K, D) << endl;
 
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
class GFG {
 
static int maximumSum(int[] A, int N, int K, int D)
{
   
    // Dp vector
    int[][][] dp = new int[N+1][K+1][D+1];
     
    for(int i = 0; i < N + 1; i++)
    {
        for(int j = 0; j < K + 1; j++)
        {
            for(int k = 0; k < D + 1; k++)
            {
                dp[i][j][k] = -1;
            }
        }
    }
 
    for (int i = 1; i <= N; i++)
    {
       
        // current element
        int element = A[i - 1];
       
        // current element modulo D
        int mod = A[i - 1] % D;
       
        // copy previous state
        dp[i] = dp[i - 1];
        for (int j = 1; j <= K; j++)
        {
           
            // Transitions
            dp[i][j][mod] = Math.max(dp[i][j][mod], element);
            for (int p = 0; p < D; p++) {
                if (dp[i - 1][j - 1][p] != -1) {
                    dp[i][j][(p + mod) % D] = Math.max(
                        dp[i][j][(p + mod) % D],
                        dp[i - 1][j - 1][p] + element);
                }
            }
        }
    }
   
    // return answer
    if (dp[N][K][0] == -1)
        return 0;
    return dp[N][K][0];
}
 
// Driver Code
public static void main(String[] args)
{
    // Input
    int N = 5, K = 3, D = 7;
    int[] A = { 1, 11, 5, 5, 18 };
 
    // Function call
    System.out.print(maximumSum(A, N, K, D));
}
}
 
// This code is contributed by SURENDRA_GANGWAR.


输出:
28

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

有效方法:这个问题可以借助动态规划解决,使用 3D dp 数组,其中dp[i][j][p]存储如果取j 个元素直到第i 个索引及其模D 时可能的最大和是p 。请按照以下步骤解决问题:

  1. 创建一个大小为 ( N+1)x(K+1)x(D)的 3D 数组 dp[][][] 并将其初始化为 -1。
  2. 1N迭代,对于每个当前索引i ,执行以下操作:
    1. 将两个变量elementmod初始化为A[i-1]A[i-1]%D
    2. dp[i-1]复制到dp[i]。
    3. 1K迭代,对于每个当前索引j ,执行以下操作:
      1. dp[i][j][mod] 更新dp[i][j][mod]元素的最大值
      2. 0D-1迭代,并且对于每个当前索引p ,执行以下操作:
        1. 如果dp[i-1][j-1][p]不等于-1,更新dp[i][j][(p+mod)%D]dp[i][j]的最大值[(p+mod)%D]dp[i-1][j-1][p]+元素。
  3. 如果dp[N][K][0]为 -1,则答案为 0。
  4. 否则,答案是dp[N][K][0]。

下面是上述方法的实现:

C++

#include 
using namespace std;
int maximumSum(vector A, int N, int K, int D)
{
    // Dp vector
    vector > > dp(
        N + 1, vector >(
                   K + 1, vector(D + 1, -1)));
    for (int i = 1; i <= N; i++) {
        // current element
        int element = A[i - 1];
        // current element modulo D
        int mod = A[i - 1] % D;
        // copy previous state
        dp[i] = dp[i - 1];
        for (int j = 1; j <= K; j++) {
            // Transitions
            dp[i][j][mod] = max(dp[i][j][mod], element);
            for (int p = 0; p < D; p++) {
                if (dp[i - 1][j - 1][p] != -1) {
                    dp[i][j][(p + mod) % D] = max(
                        dp[i][j][(p + mod) % D],
                        dp[i - 1][j - 1][p] + element);
                }
            }
        }
    }
    // return answer
    if (dp[N][K][0] == -1)
        return 0;
    return dp[N][K][0];
}
// Driver code
int main()
{
    // Input
    int N = 5, K = 3, D = 7;
    vector A = { 1, 11, 5, 5, 18 };
 
    // Function call
    cout << maximumSum(A, N, K, D) << endl;
 
    return 0;
}

Java

// Java program for the above approach
import java.util.*;
class GFG {
 
static int maximumSum(int[] A, int N, int K, int D)
{
   
    // Dp vector
    int[][][] dp = new int[N+1][K+1][D+1];
     
    for(int i = 0; i < N + 1; i++)
    {
        for(int j = 0; j < K + 1; j++)
        {
            for(int k = 0; k < D + 1; k++)
            {
                dp[i][j][k] = -1;
            }
        }
    }
 
    for (int i = 1; i <= N; i++)
    {
       
        // current element
        int element = A[i - 1];
       
        // current element modulo D
        int mod = A[i - 1] % D;
       
        // copy previous state
        dp[i] = dp[i - 1];
        for (int j = 1; j <= K; j++)
        {
           
            // Transitions
            dp[i][j][mod] = Math.max(dp[i][j][mod], element);
            for (int p = 0; p < D; p++) {
                if (dp[i - 1][j - 1][p] != -1) {
                    dp[i][j][(p + mod) % D] = Math.max(
                        dp[i][j][(p + mod) % D],
                        dp[i - 1][j - 1][p] + element);
                }
            }
        }
    }
   
    // return answer
    if (dp[N][K][0] == -1)
        return 0;
    return dp[N][K][0];
}
 
// Driver Code
public static void main(String[] args)
{
    // Input
    int N = 5, K = 3, D = 7;
    int[] A = { 1, 11, 5, 5, 18 };
 
    // Function call
    System.out.print(maximumSum(A, N, K, D));
}
}
 
// This code is contributed by SURENDRA_GANGWAR.
输出:
28

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

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程