给定大小为N的数组A[]和两个数字K和D ,任务是通过从A 中取出最多K 个元素来计算可能被D整除的最大子集和。
例子:
Input: A={11, 5, 5, 1, 18}, N=5, K=3, D=7
Output:
28
Explanation:
The subset {5, 5, 18} gives the maximum sum=(5+5+18)=28 that is divisible by 7 and also has contains atmost 3 elements
Input: A={7, 7, 7, 7, 7}, N=5, K=2, D=7
Output:
14
朴素的方法:朴素的方法是生成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 。请按照以下步骤解决问题:
- 创建一个大小为 ( N+1)x(K+1)x(D)的 3D 数组 dp[][][] ,并将其初始化为 -1。
- 从1到N迭代,对于每个当前索引i ,执行以下操作:
- 将两个变量element和mod初始化为A[i-1]和A[i-1]%D 。
- 将dp[i-1]复制到dp[i]。
- 从1到K迭代,对于每个当前索引j ,执行以下操作:
- 将dp[i][j][mod] 更新为dp[i][j][mod]和元素的最大值。
- 从0到D-1迭代,并且对于每个当前索引p ,执行以下操作:
- 如果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]+元素。
- 如果dp[N][K][0]为 -1,则答案为 0。
- 否则,答案是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 现场工作专业课程和学生竞争性编程现场课程。