Algorithm 计数总和等于k的子集数

Algorithm 计数总和等于k的子集数,algorithm,count,subset-sum,Algorithm,Count,Subset Sum,给定一个数组,我们需要找出和等于给定整数k的子集数。 请为这个问题提出一个最佳算法。这里不需要实际的子集,只需要计数即可 数组由整数组成,这些整数可以是负数,也可以是非负数 例如: 数组->{1,4,-1,10,5}abs和->9 对于{4,5}和{-1,10}的答案应该是2这是的一种变化,即-没有已知的多项式解。(事实上,子集和问题表示,很难找到是否有一个子集和给定的和求和) 可能的解决方法是蛮力(检查所有可能的子集),或者如果集合包含相对较小的整数,则可以使用伪多项式动态规划技术: f(i,

给定一个数组,我们需要找出和等于给定整数k的子集数。 请为这个问题提出一个最佳算法。这里不需要实际的子集,只需要计数即可

数组由整数组成,这些整数可以是负数,也可以是非负数

例如: 数组->{1,4,-1,10,5}abs和->9
对于{4,5}和{-1,10}的答案应该是2

这是的一种变化,即-没有已知的多项式解。(事实上,子集和问题表示,很难找到是否有一个子集和给定的和求和)

可能的解决方法是蛮力(检查所有可能的子集),或者如果集合包含相对较小的整数,则可以使用伪多项式动态规划技术:

f(i,0) = 1    (i >= 0) //succesful base clause
f(0,j) = 0    (j != 0) //non succesful base clause
f(i,j) = f(i-1,j) + f(i-1,j-arr[i])  //step
将动态规划应用于上述递归公式,可以得到时间和空间解

#include <bits/stdc++.h>

using namespace std; 

int tmp[1001][1001];  


int subset_count(int* arr, int i, int sum, int n) 
{ ` if(sum==0)
        return 1;
    if(n==0)
        return 0;
    if(tmp[n][sum]!=-1)
        return tmp[n][sum];
    else{
        if(arr[n-1]>sum)
            return tmp[n][sum]=subset_count(arr,sum, n-1);
        else{
            return tmp[n][required_sum]=subset_count(arr,sum, n- 1)+findCnt(arr,sum-arr[n-1], n-1);`
        }
    }
} 

// Driver code 

int main() 
{ ` memset(tmp,-1,sizeof(tmp));
    int arr[] = { 2, 3, 5, 6, 8, 10 }; 
    int n = sizeof(arr) / sizeof(int); 
    int sum = 10; `


    cout << subset_count(arr,sum, n); 

    return 0; 
}

使用
f(n,k)
[假设数组基于1的索引]。

此解决方案的答案之一是生成一个n的幂集,其中n是数组的大小,将等于2^n。对于0和2^N-1之间的每个数字,请检查其二进制表示形式,并包括位位于设定位置的数组中的所有值,即1。 检查您包含的所有值是否得出与所需值相等的总和。
这可能不是最有效的解决方案,但由于这是一个NP难问题,因此该问题不存在多项式时间解

以下是记忆动态规划代码,用于打印具有给定总和的子集数的计数。DP的重复值存储在“tmp”数组中。要获得DP解决方案,首先必须从问题的递归解决方案开始,然后将重复值存储在tmp数组中,以获得记忆解决方案

#include <bits/stdc++.h>

using namespace std; 

int tmp[1001][1001];  


int subset_count(int* arr, int i, int sum, int n) 
{ ` if(sum==0)
        return 1;
    if(n==0)
        return 0;
    if(tmp[n][sum]!=-1)
        return tmp[n][sum];
    else{
        if(arr[n-1]>sum)
            return tmp[n][sum]=subset_count(arr,sum, n-1);
        else{
            return tmp[n][required_sum]=subset_count(arr,sum, n- 1)+findCnt(arr,sum-arr[n-1], n-1);`
        }
    }
} 

// Driver code 

int main() 
{ ` memset(tmp,-1,sizeof(tmp));
    int arr[] = { 2, 3, 5, 6, 8, 10 }; 
    int n = sizeof(arr) / sizeof(int); 
    int sum = 10; `


    cout << subset_count(arr,sum, n); 

    return 0; 
}
#包括
使用名称空间std;
int tmp[1001][1001];
整数子集_计数(整数*arr,整数i,整数和,整数n)
{`if(总和=0)
返回1;
如果(n==0)
返回0;
如果(tmp[n][sum]!=-1)
返回tmp[n][sum];
否则{
如果(arr[n-1]>总和)
返回tmp[n][sum]=子集计数(arr,sum,n-1);
否则{
返回tmp[n][required_sum]=子集计数(arr,sum,n-1)+findCnt(arr,sum-arr[n-1],n-1)`
}
}
} 
//驱动程序代码
int main()
{`memset(tmp,-1,sizeof(tmp));
int arr[]={2,3,5,6,8,10};
int n=sizeof(arr)/sizeof(int);
整数和=10`

cout这是递归解,时间复杂度为O(2^n) 使用动态规划将时间复杂度提高为二次O(n^2)

def count_子集(arr,sum,n,count):
如果总和=0:
计数+=1
返回计数
如果n==0和sum!=0:
计数+=0
返回计数

如果arr[n-1]你尝试过任何东西吗?有什么初步想法吗?你的数组中有负数吗?整数还是浮点?有什么尝试吗?子数组存在多项式解。
子数组
。你的子集是否意味着子数组
?请给出一个例子。使用距离列表可以帮助
L={1,2,3,0,-3,-5,-6}g=2
然后
D(g,L)={-1,0,+1,-2,-5,-7,-8}
但该算法不计算有多少子集。该算法只告诉您是否存在解。即使在这之后,应用回溯,您也可以导出一个解。不是所有解。这是一个简单的解,不是最优的!是O(n^2)时间还是O(n*sum)?它是二次时间,即O(2^n)因为这是一个递归的解决方案,并且不断地重复计算同一个问题,所以你的意思是指数?二次是二次幂。@GauriShankarBadola是的!