这是子集求和问题的扩展版本。这里我们需要找到总和等于给定总和的最大大小子集的大小。
例子:
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.
Javascript
输出:
4
上述解决方案的时间复杂度为 O(sum*n)。
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。