Open In App

Find maximum subset-sum divisible by D by taking at most K elements from given array

Improve
Improve
Like Article
Like
Save
Share
Report

Given an array A[] of size N, and two numbers K and D, the task is to calculate the maximum subset-sum divisible by D possible by taking at most K elements from A.

Examples:

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

Naive Approach: The Naive approach would be to generate all subsets of A(using bit masking), and for each subset, calculate the sum, and check whether the length of the subset is not greater than K, and the sum is divisible by D, and calculating the maximum among them.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to calculate maximum sum possible by taking at
// most K elements that is divisibly by D
int maximumSum(vector<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) {
                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<int> 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{
 
// 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 the 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 the 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<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()
{
     
    // Input
    int N = 5, K = 3, D = 7;
    List<int> A = new List<int>(){ 1, 11, 5, 5, 18 };
 
    // Function call
    Console.Write(maximumSum(A, N, K, D));
}
}
 
// This code is contributed by SURENDRA_GANGWAR


Javascript




<script>
 
// JavaScript program for the above approach
 
 
// Function to calculate maximum sum possible by taking at
// most K elements that is divisibly by D
function maximumSum(A, N, K, D) {
    // variable to store final answer
    let ans = 0;
    // Traverse all subsets
    for (let i = 0; i < (1 << N); i++) {
        let sum = 0;
        let c = 0;
        for (let 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 = Math.max(ans, sum);
    }
    return ans;
}
// Driver code
 
// Input
let N = 5, K = 3, D = 7;
let A = [1, 11, 5, 5, 18];
 
// Function call
document.write(maximumSum(A, N, K, D) + "<br>");
 
</script>


Output: 

28

 

Time Complexity: O(N.2N)
Auxiliary Space: O(1)

Efficient Approach: This problem can be solved with the help of dynamic programming, with a 3D dp array, where dp[i][j][p] stores the maximum sum possible if j elements are taken till the ith index and its modulo D is p. Follow the steps to solve the problem: 

  1. Create a 3D array dp[][][] of size (N+1)x(K+1)x(D), and initialize it with -1.
  2. Iterate from 1 to N, and for each current index i, do the following:
    1. Initialize two variables element and mod to A[i-1] and A[i-1]%D.
    2. Copy dp[i-1] to dp[i].
    3. Iterate from 1 to K, and for each current index j, do the following:
      1. Update dp[i][j][mod] as the maximum of dp[i][j][mod] and element.
      2. Iterate from 0 to D-1, and for each current index p, do the following:
        1. If dp[i-1][j-1][p] is not equal to -1, Update dp[i][j][(p+mod)%D] as the maximum of dp[i][j][(p+mod)%D] and dp[i-1][j-1][p]+element.
  3. If dp[N][K][0] is -1, the answer is 0.
  4. Otherwise, the answer is dp[N][K][0].

Below is the implementation of the above approach: 

C++




#include <bits/stdc++.h>
using namespace std;
int maximumSum(vector<int> A, int N, int K, int D)
{
    // Dp vector
    vector<vector<vector<int> > > dp(
        N + 1, vector<vector<int> >(
                   K + 1, vector<int>(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<int> 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.


Python3




# Python3 code to implement the approach
def maximumSum(A, N, K, D):
 
    # Dp vector
    dp = list()
    for i in range(N + 1):
        dp.append([list() for _ in range(K + 1)])
        for j in range(K + 1):
            dp[i][j] = ([-1 for _ in range(D + 1)])
     
    for i in range(1, N + 1):
       
        # current element
        element = A[i - 1];
         
        # current element modulo D
        mod = A[i - 1] % D;
         
        # copy previous state
        dp[i] = dp[i - 1];
        for j in range(1, K + 1):
            # Transitions
            dp[i][j][mod] = max(dp[i][j][mod], element);
            for p in range(D):
                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
 
# Input
N, K, D = 5, 3, 7
A = [ 1, 11, 5, 5, 18 ];
 
# Function call
print(maximumSum(A, N, K, D));
 
# This code is contributed by phasing17


C#




// C# program to implement above approach
using System;
using System.Collections.Generic;
 
class GFG
{
 
  static int maximumSum(int[] A, int N, int K, int D)
  {
 
    // Dp vector
    int[][][] dp = new int[N+1][][];
 
    for(int i = 0 ; i < N + 1 ; i++)
    {
      dp[i] = new int[K+1][];
      for(int j = 0 ; j < K + 1 ; j++)
      {
        dp[i][j] = new int[D+1];
        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 = new int[]{ 1, 11, 5, 5, 18 };
 
    // Function call
    Console.Write(maximumSum(A, N, K, D));
 
  }
}
 
// This code is contributed by subhamgoyal2014.


Javascript




// JavaScript code to implement the approach
function maximumSum(A, N, K, D)
{
 
    // Dp vector
    let dp = [];
    for (var i = 0; i < N; i++)
    {
        dp.push([]);
        for (var j = 0; j < K + 1; j++)
            dp[i].push(new Array(D + 1).fill(-1));
    }
     
     
    for (var i = 1; i <= N; i++)
    {
     
        // current element
        var element = A[i - 1];
         
        // current element modulo D
        var mod = A[i - 1] % D;
         
        // copy previous state
        dp[i] = dp[i - 1];
        for (var j = 1; j <= K; j++)
        {
         
            // Transitions
            dp[i][j][mod] = Math.max(dp[i][j][mod], element);
            for (var 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
 
// Input
let N = 5, K = 3, D = 7;
let A = [ 1, 11, 5, 5, 18 ];
 
// Function call
console.log(maximumSum(A, N, K, D));
 
// This code is contributed by phasing17


Output: 

28

 

Time Complexity: O(NKD)
Auxiliary Space: O(NKD)

 



Last Updated : 20 Jul, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads