(决策版本)您的问题仍然是 NP 完全的。这个想法是,如果我们可以解决您的问题,那么(例如,对于每个子集大小)我们可以询问有多少集合总和小于 V,有多少集合总和小于 V-1,这两个数字的差将告诉我们是否是子集的总和正好为 V——因此我们可以解决子集和问题。[这不是一个完整的证明,因为它是图灵归约,而不是多一归约。]
但是,有一个简单的动态规划解决方案可以在 O(nLV) 时间内运行。[这不能证明 P=NP 的原因是 V 可以是输入大小的指数:使用 n 位,您可以表示高达 2 n的值。但假设你的 V 不是指数的,这不是问题。]
让 num[v][k][i] 表示 S 的前 i 个元素的大小为 k 的子集的数量,它们总和为 v。您可以将它们计算为(对于每个 i):
num[0][0][i] = 1
for v = 1 to V:
for k = 1 to L:
num[v][k][i] = num[v][k][i-1] + num[v-S[i]][k-1][i-1]
其中 S[i] 是序列中的第 i 个元素。(总和为 v 的任何大小 k 集合要么不使用 S[i],所以它被计入 num[v][k][i-1],或者它使用 S[i],这意味着其余的该子集有 k-1 个元素,仅使用序列中的前 i-1 个数字,并求和为 vS[i]。)最后,为每个小于 V 的 v 计数 num[v][L][|S|] ; 这就是你的答案。
此外,如果您仔细操作,您可以省略第三个下标(为每个 i 向下运行循环,等等);我只是为了清楚起见才包括它。