小编典典

快速解决子集总和

algorithm

考虑以下解决子集总和问题的方法:

def subset_summing_to_zero (activities):
  subsets = {0: []}
  for (activity, cost) in activities.iteritems():
      old_subsets = subsets
      subsets = {}
      for (prev_sum, subset) in old_subsets.iteritems():
          subsets[prev_sum] = subset
          new_sum = prev_sum + cost
          new_subset = subset + [activity]
          if 0 == new_sum:
              new_subset.sort()
              return new_subset
          else:
              subsets[new_sum] = new_subset
  return []

我从这里得到它:

http://news.ycombinator.com/item?id=2267392

还有一条评论说有可能使其“更有效”。

怎么样?

另外,还有其他解决问题的方法至少与上述方法一样快吗?

编辑

我对任何会加快速度的想法都很感兴趣。我发现:

https://zh.wikipedia.org/wiki/Subset_sum_problem#cite_note-
Pisinger09-2

其中提到了线性时间算法。但是我没有纸,亲爱的人们,也许您知道它是如何工作的?一个实现也许?也许完全不同的方法?

\


阅读 313

收藏
2020-07-28

共1个答案

小编典典

虽然我以前的答复介绍了polytime近似算法对这个问题,要求被
专门_为一个实现方式制成Pisinger的polytime动态规划的解决方案时,所有的_X 我_在 _X 是积极的:

from bisect import bisect

def balsub(X,c):
    """ Simple impl. of Pisinger's generalization of KP for subset sum problems
    satisfying xi >= 0, for all xi in X. Returns the state array "st", which may
    be used to determine if an optimal solution exists to this subproblem of SSP.
    """
    if not X:
        return False
    X = sorted(X)
    n = len(X)
    b = bisect(X,c)
    r = X[-1]
    w_sum = sum(X[:b])
    stm1 = {}
    st = {}
    for u in range(c-r+1,c+1):
        stm1[u] = 0
    for u in range(c+1,c+r+1):
        stm1[u] = 1
    stm1[w_sum] = b
    for t in range(b,n+1):
        for u in range(c-r+1,c+r+1):
            st[u] = stm1[u]
        for u in range(c-r+1,c+1):
            u_tick = u + X[t-1]
            st[u_tick] = max(st[u_tick],stm1[u])
        for u in reversed(range(c+1,c+X[t-1]+1)):
            for j in reversed(range(stm1[u],st[u])):
                u_tick = u - X[j-1]
                st[u_tick] = max(st[u_tick],j)
    return st

哇,真令人头疼。这需要进行校对,因为在实现的同时balsub,我无法定义正确的比较器来确定是否存在针对此SSP子问题的最佳解决方案。

2020-07-28