使用动态编程查找子集和

时间:2017-01-10 13:45:31

标签: python dynamic-programming

我正在练习动态编程,而且我正在努力调试我的代码。我们的想法是在给定数字列表的情况下查找是否可以求和。这是我的代码:

a = [2,3,7,8,10]
sum = 11
b = list(range(1, sum+1))
m = [[False for z in range(len(b))] for i in range(len(a))]

for i, x in enumerate(b):
    for j, y in enumerate(a):
        if x==y:
            m[j][i]=True
        elif y<x:
            m[j][i] = m[j-1][i]
        else:
            m[j][i] = m[j-1][i] or m[j-i][y-x]

for i, n in enumerate(m):
    print(a[i], n)

这是输出:

2 [False, True, False, False, False, False, False, False, False, False, False]
3 [False, True, True, False, False, False, False, False, False, False, False]
7 [False, True, True, False, True, True, True, False, False, False, False]
8 [False, True, True, False, True, True, True, True, False, False, False]
10 [False, True, True, False, True, True, True, True, True, True, False]

据我所知,在我的else语句中,该算法应该上升1行,然后查看x和y的差异,并检查该槽是否可行。因此,例如在最明显的情况下,最后一行中的最后一个元素。这将是10(y)-11(x),它应该一直回到它上面的行上的索引1,这正如我们所知道的那样。不完全确定我做错了什么,理解这一点的任何帮助都将非常感激。

1 个答案:

答案 0 :(得分:4)

鉴于您只提供正值,我并不完全理解为什么您需要二维列表。您只需使用1d列表:

coins = [2,3,7,8,10]
sum = 11

接下来,我们初始化列表possible,说明是否有可能获得某个值。我们将possible[0]设置为True,因为这笔款项可以在没有硬币的情况下完成。

possible = [False for _ in range(sum+1)]
possible[0] = True

现在,您遍历每个硬币,并在列表上进行迭代,并且#34;升级&#34;尽可能的价值:

for coin in coins:
    for i in range(sum-coin,-1,-1):
        if possible[i]:
            possible[i+coin] = True

之后,列表possible会显示从0到(包括sum)的每个值,是否可以构建它。因此,如果possible[sum]True,则可以构建sum

对于给定的coinssum,可获得:

>>> possible
[True, False, True, True, False, True, False, True, True, True, True, True]

所以价值0235789,{{1 },10可以用硬币构建。

编辑:跟踪硬币

您还可以通过稍微修改代码来跟踪硬币:

11

现在可能看起来像:

possible = [None for _ in range(sum+1)]
possible[0] = []
for coin in coins:
    for i in range(sum-coin,-1,-1):
        if possible[i] is not None:
            possible[i+coin] = possible[i]+[coin]

所以>>> possible [[], None, [2], [3], None, [2, 3], None, [7], [8], [2, 7], [10], [3, 8]] 可以用硬币0构建(没有硬币); []可以使用2(一个值为[2]的硬币),2 3[3] 5,等