【问题标题】:Equal sum subsets hybrid等和子集混合
【发布时间】:2009-02-08 11:21:27
【问题描述】:

问题如下:

给定一组正整数 { a1 , a2 , a3 , ... , an },其中没有相同的数字(a1 只存在一次,a2 只存在一次,...)例如 A = { 12 , 5 ,7 ,91 }。 问题:是否存在 A 的两个不相交子集 A1 = { b1,b2,...,bm } 和 A2 = { c1,c2,...,ck} 使得 b1+b2+...+bm = c1+ c2+...+ck ?

注意以下几点:A1 和 A2 不是必须覆盖 A,因此问题不会自动归结为子集和问题。 例如 A = {2,5,3,4,8,12} A1= {2,5} 所以 A1 的总和是 7 A2= {3,4} 所以 A2 的总和是 7 我们找到了具有所描述属性的 A 的两个不相交的子集,因此问题解决了。

我该如何解决这个问题?我能比找到所有可能的(不相交的)子集、计算它们的总和并找到两个相等的总和更好吗?

感谢您的宝贵时间。

【问题讨论】:

    标签: algorithm complexity-theory subset-sum


    【解决方案1】:

    没问题,这是O(1) 解决方案。

    A1 = {}; 
    A2 = {};
    sum(A1) == sum(A2) /* == 0 */
    

    QED。


    说真的,您可以进行的一项优化(假设我们谈论的是正数)是只检查小于或等于 sum(A)/2 的子集。

    对于A 中的每个元素,都有三个选项使其成为O(3^N)

    1. 放入A1
    2. 放入A2
    3. 丢弃它

    这是 Perl 中的一个简单的解决方案(计算匹配项,如果您只想测试存在性,可以提前返回)。

    use List::Util qw/sum/;
    
    my $max = sum(@ARGV)/2;
    my $first = shift(@ARGV); # make sure we don't find the empty set (all joking aside) and that we don't cover same solution twice (since elements are unique)
    my $found = find($first,0, @ARGV);
    print "Number of matches: $found\n";
    
    sub find {
        my ($a, $b, @tail) = @_;
        my $ret = $a == $b? 1 : 0; # are a and b equal sub-sets?
        return $ret unless @tail;
    
        my $x = shift @tail;
        $ret += find($a + $x, $b, @tail) if $a + $x <= $max; # put x in a
        $ret += find($a, $b + $x, @tail) if $b + $x <= $max; # put x in b
        return $ret + find($a, $b, @tail); # discard x
    }
    

    【讨论】:

    • 问题中提到的 O(2^N) 解决方案比这个 O(3^N) 解决方案更好:-) [代价是也需要 O(2^N) 空间.]
    • 是的,但我的 O(1) 解决方案仍然胜过它;o)
    • 当然。完美的 O(1) 解决方案。 :-)
    • @ShreevatsaR:问题中提到的解决方案不是 O(2^N),因为有超过 2^N 个不相交的子集(已经有 2^N 个不相交的子集,其并集是整套!)我很确定正好有 3^N 对不相交的子集,因为每一对都可以表示为 (B, C, ABC) 并且 Motti 的决策树只列举了所有这些可能性一次 :)
    • @j_random_hacker:不,只要某个键有 2 个值,您就可以停止。并且没有必要测试:取这两个集合(比如 A 和 B),从每个集合中删除它们的交集(比如 C):那么 A\C 和 B\C 是两个不相交的集合,总和相同。
    【解决方案2】:

    如果答案是否定的,那么所有 n 个数字的总和至少为 2^n-1。因此,例如,如果 n 很大,并且数字是 32 位整数,那么答案几乎总是肯定的。如果 n 很小,您可能可以蛮力。

    最困难的情况可能是 n 在 30 左右时。

    【讨论】:

      【解决方案3】:

      我认为你可以像子集和问题一样解决它。取布尔函数 Q(i,s),如果 a0,a1,...,ai 有一个总和为 s 并包含 ai 的子集,则该函数为真。您可以使用动态编程为所有 i 和 s 计算它(这是标准方法)。然后,您可以扫描 Q 的所有值以查找在其关联行中具有多个真值的 s。

      如果存在这样的 s,则意味着您找到了两个具有相同总和的不同子集。它们可能不是不相交的,但是您可以从每个集合中删除公共元素并获得两个总和相等的不相交集合。不过,其中一个可能是空的。

      【讨论】:

        【解决方案4】:

        这个问题似乎至少和 SUBSET-SUM 一样难。如果我们可以找到 A 的两个子集:B = {b1,...,bp} 和 C = {c1,...,cq} 使得 b1+...+bp = -c1-...-cq,或者如果我们确定不存在,那么我们已经解决了 SUBSET-SUM(A)(忽略 0 ∈ A 的平凡情况)。

        我不确定您的意思是 B 和 C 没有义务覆盖 A,因此问题不会自动归结为子集和问题。请检查SUBSET-SUM的定义。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-10-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-12-14
          • 1970-01-01
          • 2017-05-09
          • 2021-07-15
          相关资源
          最近更新 更多