如何按以下顺序生成所有可能的总和?

时间:2016-09-26 11:24:25

标签: python-3.x dynamic-programming

假设我有一个数组,可以说[1,2,3,4]:

我想找到如下总和:

首先我生成像:

这样的对
(1 2 3 4)

(123)(4)

(1)(234)

(12)(34)

(12)(3)(4)

(1)(23)(4)

(1)(2)(34)

(1)(2)(3)(4)

然后,ans将是一个组中元素的总和乘以该组的长度(对于所有可能的组)

例如,在安排(123)(4)中,总和将是

(1+2+3)*3 + (4)*1

我只想要最终总和,它是所有这些值的总和,而不是实际的组。我怎么能这样做?

我能够通过首先生成所有可能的组然后找到总和

来实现

但是因为我只需要总和而不是实际的群体,是否有更好的方法

1 个答案:

答案 0 :(得分:1)

安排数量为2**(len(L)-1)。 8个元素的列表产生128种不同的排列。这是一个指数问题。您可以生成所有可能的解决方案,然后计算每个答案,或者您可以动态计算每个答案。无论哪种方式,它仍然是exp。

def part1(L, start, lsum):
    if start == len(L):
        print lsum
    else:
        for i in range(start, len(L)):
            left = sum(L[start:i+1]) * (i-start+1)
            part1(L, i + 1, lsum + left)

def part2(L, M, X, start):
    if start == len(L):
        M.append(X)
        print sum([sum(x) * len(x) for x in X])
    else:
        for i in range(start, len(L)):
            part2(L, M, X + [L[start:i+1]], i + 1)

例如:

>>> part1(L, 0, 0)
10
17
15
28
13
20
22
40
>>> M = []
>>> part2(L, M, [], 0)
10
17
15
28
13
20
22
40

编辑:O(n ** 3)

中所有总和的总和

对于L = [1,2,3,4,5,6]

[[[1],                  [2],            [3],            [4],            [5],            [6]],
 [[1],                  [2],            [3],            [4],            [5, 6]],
 [[1],                  [2],            [3],            [4, 5],                         [6]],
 [[1],                  [2],            [3],            [4, 5, 6]],
 [[1],                  [2],            [3, 4],                         [5],            [6]],
 [[1],                  [2],            [3, 4],                         [5, 6]],
 [[1],                  [2],            [3, 4, 5],                                      [6]],
 [[1],                  [2],            [3, 4, 5, 6]],
 [[1],                  [2, 3],                         [4],            [5],            [6]],
 [[1],                  [2, 3],                         [4],            [5, 6]],
 [[1],                  [2, 3],                         [4, 5],                         [6]],
 [[1],                  [2, 3],                         [4, 5, 6]],
 [[1],                  [2, 3, 4],                                      [5],            [6]],
 [[1],                  [2, 3, 4],                                      [5, 6]],
 [[1],                  [2, 3, 4, 5],                                                   [6]],
 [[1],                  [2, 3, 4, 5, 6]],
 [[1, 2],                               [3],            [4],            [5],            [6]],
 [[1, 2],                               [3],            [4],            [5, 6]],
 [[1, 2],                               [3],            [4, 5],                         [6]],
 [[1, 2],                               [3],            [4, 5, 6]],
 [[1, 2],                               [3, 4],                         [5],            [6]],
 [[1, 2],                               [3, 4],                         [5, 6]],
 [[1, 2],                               [3, 4, 5],                                      [6]],
 [[1, 2],                               [3, 4, 5, 6]],
 [[1, 2, 3],                                            [4],            [5],            [6]],
 [[1, 2, 3],                                            [4],            [5, 6]],
 [[1, 2, 3],                                            [4, 5],                         [6]],
 [[1, 2, 3],                                            [4, 5, 6]],
 [[1, 2, 3, 4],                                                         [5],            [6]],
 [[1, 2, 3, 4],                                                         [5, 6]],
 [[1, 2, 3, 4, 5],                                                                      [6]],
 [[1, 2, 3, 4, 5, 6]]]

似乎有一种模式。奇怪的情况是:将序列的第一个元素作为最小元素的集合作为有序集合,有32个。但是其余的全部都是16.对于列表的每个元素,我添加包含的所有集合该元素作为第一个排序元素。

def part3(L):
    ret = 0
    for i in range(len(L)):
        p = 0
        for k in range(len(L) - i - 1):
            p += sum(L[i:i+k+1]) * (k+1) * 2**(len(L) - i - k - 2)
        p += sum(L[i:]) * (len(L) - i)
        ret += p * max(1, 2**(i-1))
    return ret

edit2:将它降低到O(n ^ 2)你需要使用DP。建立一个总和表来计算O(1)中的每个总和。使用S [i] = S [i-1] + L [i]构建数组S,求和(L [a:b])为S [b] - S [a]。