子集和问题的这个变体更容易解决吗?

Posted

技术标签:

【中文标题】子集和问题的这个变体更容易解决吗?【英文标题】:Is this variant of the subset sum problem easier to solve? 【发布时间】:2010-09-27 10:07:03 【问题描述】:

我有一个与 subset sum problem 相关的问题,我想知道这些差异是否使它更容易,即可以在合理的时间内解决。

给定一个值 V、一个集合大小 L 和一个数字序列 [1,N] S,S 的多少个大小为 L 的子集总和小于 V?

这在三个方面不同于子集和问题:

    我关心的是有多少子集小于小于给定值,而不是有多少子集等于。 子集大小是固定的。 我关心有多少集合总和小于 V,而不仅仅是是否存在。

有没有合理有效的算法来解决这个问题?

编辑: 显然,这可以使用组合生成算法在 O(N choose L) 中完成。我真正感兴趣的是可以显着加快速度的巧妙技巧。

【问题讨论】:

这不只是 Knapsack problem 的扭曲吗?可能是我错了。 【参考方案1】:

(决策版本)您的问题仍然是 NP 完全的。这个想法是,如果我们可以解决您的问题,那么(例如,对于每个子集大小)我们可以询问有多少个集合总和小于 V,有多少总和小于 V-1,这两个数字的差将告诉我们是否是子集的总和正好为 V——因此我们可以解决子集和问题。 [这不是一个完整的证明,因为它是Turing reduction,而不是many one reduction。]

但是,有一个简单的动态规划解决方案可以在 O(nLV) 时间内运行。 [这不能证明 P=NP 的原因是 V 可以是输入大小的指数:使用 n 位,您可以表示高达 2n 的值。但假设你的 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 向下运行循环,等等);我只是为了清楚起见才包括它。

【讨论】:

【参考方案2】:

我不准备提供证明,但这听起来可能适合动态编程方案:将大小为 2 的子集列表制成表格,将它们用于计算机大小为 3 的子集等,这样你只需要检查一小部分潜在客户。

【讨论】:

【参考方案3】:

想到的一个优化是:订购您的序列(如果不是这样的话)。从它的开头选择前 L-1 个项目,然后选择最后一个项目,使其成为可能的最大值(序列中的下一个最大值会给出一个太大的总和)。丢弃序列的其余部分,因为这些项目无论如何都不能成为有效子集的一部分。

在那之后我猜又是全搜索了。但话又说回来,也可能有其他优化。

【讨论】:

【参考方案4】:

子集和问题的动态规划解决方案会生成一个包含该答案的表(即 V 乘 N 的布尔表,其中 V 是最大元素数,N 是集合中可以包含的最大项目数满足约束;如果

【讨论】:

【参考方案5】:

如果只是正整数,你可以做一个验证步骤如果你需要;

取集合中 L-1 个最小整数的和。如果这是和 X,那么如果问题应该有解决方案,则 n-X 必须低于最大元素。想一想,你可以这样消除其他L...

【讨论】:

【参考方案6】:

好吧,一方面,既然您指定了 size=L,那么即使您想不出任何聪明的方法而只是使用蛮力,在最坏的情况下,您将拥有(N 选择 L)单独的总和,所以它是比 n^^L 好一点(嗯,L+1,因为你会对每个子集求和)。

【讨论】:

【参考方案7】:

这听起来像是一个 n 选择 k 类别的问题。 Skiena 的算法设计手册中介绍了生成 n 的 k 子集,并且该书建议按字典顺序(例如递归)枚举相关子集。然后对每个子集进行求和和比较。

如果您有一个排序集,您大概可以从解决方案空间中剪除不可能的解决方案。

【讨论】:

【参考方案8】:

也许动态规划公式适用于 FPTAS 的 PTAS。

【讨论】:

以上是关于子集和问题的这个变体更容易解决吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何从雪花中的变体列创建子集?

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

vba 变体数组错误

总和小于 M 的大小为 K 的子集的最大总和

在 R 子集设置中不使用子集()并以更简洁的方式使用 [ 来防止拼写错误?

我们可以按风格组织存储库并构建变体吗