Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 等和子集_Algorithm_Subset Sum - Fatal编程技术网

Algorithm 等和子集

Algorithm 等和子集,algorithm,subset-sum,Algorithm,Subset Sum,我想计算一个集合S中存在多少对不相交的子集S1和S2(S1 U S2可能不是S),其中S1中的元素之和=S2中的元素之和 假设我已经计算了所有可能的2^n子集的所有子集和。 如何找到有多少不相交子集的和相等 对于和值a,我们可以使用和为a/2的子集的计数来解决这个问题吗 例如: S={1,2,3,4} 各种可能的S1和S2组包括: S1={1,2}和S2={3} S1={1,3}和S2={4} S1={1,4}和S2={2,3} 以下是问题的链接: 这里有一个clojure解决方案 它将s定义为

我想计算一个集合S中存在多少对不相交的子集S1和S2(S1 U S2可能不是S),其中S1中的元素之和=S2中的元素之和

假设我已经计算了所有可能的2^n子集的所有子集和。 如何找到有多少不相交子集的和相等

对于和值a,我们可以使用和为a/2的子集的计数来解决这个问题吗

例如: S={1,2,3,4}

各种可能的S1和S2组包括:

S1={1,2}和S2={3}

S1={1,3}和S2={4}

S1={1,4}和S2={2,3}

以下是问题的链接:
这里有一个clojure解决方案

它将s定义为1,2,3,4的集合 然后将所有子集定义为大小为1-3的所有集合的列表

一旦定义了所有子集,它将查看所有子集对,并仅选择不相等、不与原始集并集且其和相等的对

(require 'clojure.set)
(use 'clojure.math.combinatorics)

(def s #{1, 2, 3, 4})
(def subsets (mapcat #(combinations s %) (take 3 (iterate inc 1))))

(for [x all-subsets y all-subsets 
          :when (and (= (reduce + x) (reduce + y)) 
                     (not= s (clojure.set/union (set x) (set y))) 
                     (not= x y))] 
      [x y])
产生以下结果:

([(3) (1 2)] [(4) (1 3)] [(1 2) (3)] [(1 3) (4)])

[编辑:修复了愚蠢的复杂性错误。谢谢kash!]

事实上,我相信你需要使用O(3^n)算法来回答这个问题——O(2^n)分割算法只足以枚举其并集是整个地面集的所有不相交子集对

如我所链接的答案所述,对于每个元素,您基本上决定是否:

  • 把它放在第一盘
  • 把它放在第二盘,或者
  • 别理它
  • 考虑所有可能的方法,生成一棵树,其中每个顶点有3个子节点:因此是O(3^n)时间。需要注意的一点是,如果生成一个解(S1,S2),则不应同时计算解(S2,S1):这可以通过在构建两个集合时始终保持两个集合之间的不对称来实现,例如,强制要求S1中的最小元素必须始终小于S2中的最小元素。(这种不对称执行具有将执行时间减半的良好副作用:)


    特殊(但在实践中可能很常见)情况下的加速
    如果您预计集合中会有许多小数字,那么还有另一种可能的加速:首先,按递增顺序对列表中的所有数字进行排序。选择一些最大值m,越大越好,但足够小,可以提供一个m大小的整数数组。现在,我们将数字列表分为两部分,分别进行处理:一个初始数字列表,其总和最多为m(此列表可能非常小),其余部分。假设第一个k没有解决特定的编程语言问题,您可以使用任何编程语言。假设我有一个大小为2^n的数组子集[],它具有所有可能子集的子集和。现在,我们如何计算具有相同和的不相交子集的数量。这可以很容易地简化为划分问题(确定
    S
    可以划分为两个等和的分区),这是NP完全的,所以我希望你不要期望多项式时间解……是的,我不期望多项式算法。我只是在寻找分区问题的优化。假设N为20,即数组的最大大小为20。子集数=2^20。现在,如果我们将分区算法应用于每个子集,时间复杂度相当高。我试图解决一个问题,归结到这一点。这是它的链接@卡什:哎呀,是的,我知道!我现在就修。