【问题标题】:Subset sum variation子集和变化
【发布时间】:2015-12-24 05:35:55
【问题描述】:

给定一个整数 ns 大小不同的集合,但以从 0s_i 的正升序数字作为元素。让一个好的总和在这里定义为a_1 + a_2 + ... + a_s = n。计算存在多少总和,当您从对应的集合 s_i 中为每个 a_i 取一个元素时。

我试图生成任何可能的方式并省略那些可省略的方式,即当你有例如s=3n=1 并且给你集合s_0={0,1}s_1={0,1,2,3}s_2={0,1,2},那么你可以省略检查总和 0 + 0 + a_3,因为 a_3 不够大。 我已经为每个可能的序列应用了正常子集和的动态编程解决方案,但是,我得到的结果比我应该得到的要大得多,而且速度也很慢。

有什么好的算法可以在这里应用吗?

【问题讨论】:

    标签: algorithm dynamic-programming subset-sum


    【解决方案1】:

    您可以通过使用两个字典(数组也可以工作,但字典更好)来对经典的子集求和解决方案进行细微的修改:

    dp[i] = dictionary of sums we can obtain using the first i sets and their counts
    
    
    dp[0, <elements in s[0]>] = 1
    for i = 1 to s - 1:
      for each element x in dp[i - 1]:
        for each element k in s[i]:
          dp[i, x + k] += dp[i - 1, x]
    

    复杂性会非常大,但我认为您无法减少它。不过它应该可以工作。

    您可以在内存中只保留两个字典,因为您只需要当前和以前的字典。

    Python 代码:

    def solve(s, n):
    
        dp = [dict()] * len(s)
    
        for k in s[0]:
            dp[0][k] = 1
        for i in range(1, len(s)):
            dp[i] = dict()
            for x in dp[i - 1]:
                for k in s[i]:
                    if x + k in dp[i]:
                        dp[i][x + k] += dp[i - 1][x]
                    else:
                        dp[i][x + k] = dp[i - 1][x]
    
        return dp[len(s) - 1][n]
    
    print(solve([[0,1,2],[0,1,2]], 3)) # prints 2
    print(solve([[0,1,2],[0,1,2,3,4],[0,1,2,3,4]], 5)) # prints 13
    

    【讨论】:

    • @user5379430 它是s 字典的数组。字典中的每个条目(k, v) 意味着您可以通过v 方式组成一些k
    • @user5379430 in dp[s - 1][n].
    • @user5379430 我发布了一个 Python 代码,它为您的示例提供了 2。如果您发布代码,我们或许可以帮助您调试它。
    • 所以我似乎对dp 仍有一些误解问题,正如您解释的那样,它似乎是 1 暗,但您将其用作 2 暗。
    • @user5379430 它是 2d,因为 dp 的每个元素都是一个字典。所以字典增加了第二个维度。你熟悉字典吗?你想用什么语言编写代码?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-29
    • 2011-05-03
    • 1970-01-01
    • 2020-05-18
    • 2017-03-28
    • 1970-01-01
    相关资源
    最近更新 更多