查找总和等于 k ​​的子集的数量

Posted

技术标签:

【中文标题】查找总和等于 k ​​的子集的数量【英文标题】:Finding the number of subsets with sum equal to k 【发布时间】:2015-03-11 13:36:29 【问题描述】:

谁能解释一下动态算法,它找到总和等于 k ​​的子集数。 我在谷歌搜索,但找不到任何简单的解释!对不起我的英语不好! 代码如下:

int numbers[MAX];

int GetmNumberOfSubsets()
    
        int dp[MAX];
        dp[0] = 1;
        int currentSum = 0;
        for (int i = 0; i < numbers.length; i++)
        
            currentSum += numbers[i];
            for (int j = min(sum, currentSum); j >= numbers[i]; j--)
                dp[j] += dp[j - numbers[i]];
        

        return dp[sum];
    

【问题讨论】:

【参考方案1】:

您的 DP 解决方案应该是 2 维的,1 维表示总和,1 维表示元素数量。

定义这个解决方案的递归公式是:

DP(x,i) = 0    x < 0
DP(0,i) = 1
DP(x,0) = 0    x > 0
DP(x,i) = DP(x-numbers[i],i-1) + DP(x,i-1)

它应该是这样的:

    int dp[MAX+1][sum+1];
    int i, x;
    for (i = 0; i < MAX+1; i++)  
         dp[i][0] = 1;
    
    for (x = 1; x < sum+1; x++)  
         dp[0][x] = 0
    
    for (i = 1; i < MAX+1; i++)  
       for (x = 1; x < sum+1; x++)  
           dp[i][x] = dp[i-1][x];
           if (x >= numbers[i])
             dp[i][x] += dp[i][x-numbers[i]];
        
     
    return dp[MAX][sum];

(希望我没有遇到小问题,没有对其进行测试 - 但它应该让您知道一旦递归公式明确后如何实现它)

【讨论】:

@SvendHansen 为什么?这个想法是取消“通过”所需总和的解决方案,因此每个达到 x 负值的解决方案都将产生 0 个解决方案。 测试if (x &lt;= numbers[i])怎么样。那不应该是&gt;=吗?确保下一行的索引不会为负数?【参考方案2】:

您可以使用以下示例来查找总和等于 k ​​的子集的数量:

#include <iostream>

using std::cout;
using std::cin;

int count = 0,K;
void noofsubsets(int arr[], int sum, int N)
    if(N==0)
        if(sum==K)
            count++;
        return;
    
    noofsubsets(arr, sum, N-1);
    noofsubsets(arr, sum+arr[N-1], N-1);

【讨论】:

仅仅发布一些代码并没有太大帮助。你能解释一下你的代码吗?这样其他人就可以理解并从您的答案中学习,而不仅仅是从网络上复制和粘贴一些代码。【参考方案3】:

这是一个使用递归的解决方案... 考虑两种情况 i) 包括数组的第一个元素。 ii) 没有第一个数组元素。

`

def subSetsSumK(arr, v, k) :

    if (k == 0) :
        for value in v :
            print(value, end=" ")
        print()
        return
    
    if (len(arr)== 0):
        return
    si=0
    v1 = [] + v

    v1.append(arr[si])

    subSetsSumK(arr[1:], v1, k - arr[si])
    subSetsSumK(arr[1:], v, k)
   
def subSetsSumK(arr, k):

    v = []
    subSetsSumK(arr,v, k)


# Driver code

arr = [ 2,1,3,2 ]
k_sum = 4
subSetsSumK(arr,k)

【讨论】:

以上是关于查找总和等于 k ​​的子集的数量的主要内容,如果未能解决你的问题,请参考以下文章

总和大于或等于 k ​​的最小子集

回溯 - 给定一组数字,找到总和等于 M 的所有子集(给定 M)

划分为k个相等的子集

动态规划算法:硬币的最大总和(小于或等于k)

698. 划分为k个相等的子集(Python)

查找任何行的总和是不是等于具有 SUM、ANY、SIZE 的任何列的总和