📌  相关文章
📜  给定总和的最大大小子集

📅  最后修改于: 2021-05-05 02:59:08             🧑  作者: Mango

这是子集总和问题的扩展版本。在这里,我们需要找到总和等于给定总和的最大子集的大小。
例子:

Input : set[] = {2, 3, 5, 7, 10, 15},
         sum  = 10
Output : 3
The largest sized subset with sum 10
is {2, 3, 5}

Input : set[] = {1, 2, 3, 4, 5}
         sum = 4
Output : 2


这是对子集总和问题的进一步增强,不仅可以判断子集是否可能,而且还可以使用DP来判断最大子集。
要解决子集和问题,请使用与子集和问题中给出的DP方法相同的方法。为了进一步计算最大子集,我们使用另一个DP数组(称为“计数数组”),其中count [i] [j]是最大

  • 计数[i] [j-1]。这里不考虑当前要素。
  • count [i-X] [j-1] +1。这里X是为子集选择的当前元素的值。
C++
// A Dynamic Programming solution for subset
// sum problem+ maximal subset value.
#include
using namespace std;
 
    // Returns size of maximum sized subset
    // if there is a subset of set[] with sun
    // equal to given sum. It returns -1 if there
    // is no subset with given sum.
    int isSubsetSum(int set[], int n, int sum)
    {
        // The value of subset[i][j] will be true if there
        // is a subset of set[0..j-1] with sum equal to i
        bool subset[sum + 1][n + 1];
        int count[sum + 1][n + 1];
 
        // If sum is 0, then answer is true
        for (int i = 0; i <= n; i++)
        {
            subset[0][i] = true;
            count[0][i] = 0;
        }
     
        // If sum is not 0 and set is empty,
        // then answer is false
        for (int i = 1; i <= sum; i++)
        {
            subset[i][0] = false;
            count[i][0] = -1;
        }
 
        // Fill the subset table in bottom up manner
        for (int i = 1; i <= sum; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                subset[i][j] = subset[i][j - 1];
                count[i][j] = count[i][j - 1];
                if (i >= set[j - 1])
                {
                    subset[i][j] = subset[i][j] ||
                                subset[i - set[j - 1]][j - 1];
 
                    if (subset[i][j])
                        count[i][j] = max(count[i][j - 1],
                                    count[i - set[j - 1]][j - 1] + 1);
                }
            }
        }
 
        return count[sum][n];
    }
 
// Driver code
int main()
{
    int set[] = { 2, 3, 5, 10 };
    int sum = 20;
    int n = 4;
    cout<< isSubsetSum(set, n, sum);
}
 
// This code is contributed by DrRoot_


Java
// A Dynamic Programming solution for subset
// sum problem+ maximal subset value.
class sumofSub {
 
    // Returns size of maximum sized subset if there
    // is a subset of set[] with sun equal to given sum.
    // It returns -1 if there is no subset with given sum.
    static int isSubsetSum(int set[], int n, int sum)
    {
        // The value of subset[i][j] will be true if there
        // is a subset of set[0..j-1] with sum equal to i
        boolean subset[][] = new boolean[sum + 1][n + 1];
        int count[][] = new int[sum + 1][n + 1];
 
        // If sum is 0, then answer is true
        for (int i = 0; i <= n; i++) {
            subset[0][i] = true;
            count[0][i] = 0;
        }
 
        // If sum is not 0 and set is empty,
        // then answer is false
        for (int i = 1; i <= sum; i++) {
            subset[i][0] = false;
            count[i][0] = -1;
        }
 
        // Fill the subset table in bottom up manner
        for (int i = 1; i <= sum; i++) {
            for (int j = 1; j <= n; j++) {
                subset[i][j] = subset[i][j - 1];
                count[i][j] = count[i][j - 1];
                if (i >= set[j - 1]) {
                    subset[i][j] = subset[i][j] ||
                       subset[i - set[j - 1]][j - 1];
 
                    if (subset[i][j])
                        count[i][j] = Math.max(count[i][j - 1],
                             count[i - set[j - 1]][j - 1] + 1);
                }
            }
        }
 
        return count[sum][n];
    }
 
    /* Driver program to test above function */
    public static void main(String args[])
    {
        int set[] = { 2, 3, 5, 10 };
        int sum = 20;
        int n = set.length;
        System.out.println(isSubsetSum(set, n, sum));
    }
}


Python3
# Python3 program to implement
# the above approach
 
# A Dynamic Programming solution 
# for subset sum problem+ maximal
# subset value.
# Returns size of maximum sized subset
# if there is a subset of set[] with sun
# equal to given sum. It returns -1 if there
# is no subset with given sum.
def isSubsetSum(arr, n, sum):
     
    # The value of subset[i][j] will
    # be true if there is a subset of
    # set[0..j-1] with sum equal to i
    subset = [[False for x in range(n + 1)]
                     for y in range (sum + 1)]
    count = [[0 for x in range (n + 1)]
                for y in range (sum + 1)]
 
    # If sum is 0, then answer is true
    for i in range (n + 1):
        subset[0][i] = True
        count[0][i] = 0
     
    # If sum is not 0 and set is empty,
    # then answer is false
    for i in range (1, sum + 1):
        subset[i][0] = False
        count[i][0] = -1
         
 
    # Fill the subset table in bottom up manner
    for i in range (1, sum + 1):
        for j in range (1, n + 1):
            subset[i][j] = subset[i][j - 1]
            count[i][j] = count[i][j - 1]
            if (i >= arr[j - 1]) :
                subset[i][j] = (subset[i][j] or
                                subset[i - arr[j - 1]][j - 1])
 
                if (subset[i][j]):
                    count[i][j] = (max(count[i][j - 1],
                                    count[i - arr[j - 1]][j - 1] + 1))
    return count[sum][n]
 
# Driver code
if __name__ == "__main__":
   
    arr = [2, 3, 5, 10]
    sum = 20
    n = 4
    print (isSubsetSum(arr, n, sum))
 
# This code is contributed by Chitranayal


C#
// A Dynamic Programming solution for subset
// sum problem+ maximal subset value.
using System;
 
class sumofSub {
 
    // Returns size of maximum sized subset
    // if there is a subset of set[] with sun
    // equal to given sum. It returns -1 if there
    // is no subset with given sum.
    static int isSubsetSum(int[] set, int n, int sum)
    {
        // The value of subset[i][j] will be true if there
        // is a subset of set[0..j-1] with sum equal to i
        bool[, ] subset = new bool[sum + 1, n + 1];
        int[, ] count = new int[sum + 1, n + 1];
 
        // If sum is 0, then answer is true
        for (int i = 0; i <= n; i++) {
            subset[0, i] = true;
            count[0, i] = 0;
        }
 
        // If sum is not 0 and set is empty,
        // then answer is false
        for (int i = 1; i <= sum; i++) {
            subset[i, 0] = false;
            count[i, 0] = -1;
        }
 
        // Fill the subset table in bottom up manner
        for (int i = 1; i <= sum; i++) {
            for (int j = 1; j <= n; j++) {
                subset[i, j] = subset[i, j - 1];
                count[i, j] = count[i, j - 1];
                if (i >= set[j - 1]) {
                    subset[i, j] = subset[i, j] ||
                                   subset[i - set[j - 1], j - 1];
 
                    if (subset[i, j])
                        count[i, j] = Math.Max(count[i, j - 1],
                                      count[i - set[j - 1], j - 1] + 1);
                }
            }
        }
 
        return count[sum, n];
    }
 
    /* Driver program to test above function */
    public static void Main()
    {
        int[] set = { 2, 3, 5, 10 };
        int sum = 20;
        int n = set.Length;
        Console.WriteLine(isSubsetSum(set, n, sum));
    }
}
 
// This code is contributed by vt_m.


输出:

4


上述解决方案的时间复杂度为O(sum * n)。