Python 用动态规划求子集和

Python 用动态规划求子集和,python,dynamic-programming,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:

我正在练习动态编程,我正在努力调试我的代码。这样做的目的是在给定一系列数字的情况下,找出一个和是否可能。这是我的密码:

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)

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

如果您只输入了正值,我不太明白您为什么需要二维列表。您可以简单地使用1d列表:

coins = [2,3,7,8,10]
sum = 11
接下来,我们初始化列表
可能
,该列表说明是否可能获得某个值。我们将
可能的[0]
设置为
,因为这个总数可以在没有硬币的情况下完成

possible = [False for _ in range(sum+1)]
possible[0] = True
现在,您对每个硬币进行迭代,并在列表上进行迭代,如果可能,“升级”值:

for coin in coins:
    for i in range(sum-coin,-1,-1):
        if possible[i]:
            possible[i+coin] = True
之后,列表
可能的
显示从
0
到(包括
求和
)的每个值是否可以构造它。因此,如果
可能的[sum]
True
,则可以构造
sum

对于给定的
硬币
总和
,可以得到:

>>> possible
[True, False, True, True, False, True, False, True, True, True, True, True]
因此,可以用硬币构造值
0
2
3
5
7
8
9
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
[2,3]
,等等来构造。

我不太明白为什么需要一个二维列表…@WillemVanOnsem这不是解决这个问题的动态编程方法吗?不是本身。你知道你在这里干什么吗?如果你只是想知道你是否可以使用这些硬币来求和到给定的值,你可以使用1d列表。你可以重复使用一枚硬币,或者每个数字只能使用一次吗?是的@WillemVanOnsem我明白我在做什么,我论文中的矩阵是有意义的。但代码并不完全正确。我可以用贪婪的方法或者排序的左右方法来解决这个问题,但是我“我试图通过动态规划来实现这一点。我不想得到我感兴趣的答案,更想通过DPAh解决这个问题,好吧,我得到了这个解决方案。但是如果我使用1D数组,就不可能跟踪用于获取解决方案的硬币,对吗?@dumby.Fat.Cat:事实上,只需稍微修改一下代码。啊,这是一个比算法书籍建议的更好的解决方案。非常感谢。我仍然不能完全确定为什么我的代码不能工作,但调试起来比1d要困难得多array@Stupid.Fat.Cat:请记住,这只适用于正值。如果我想保留此解决方案并将其应用于负值,我认为可以对负值进行规范化。如果我将“最大”负值调整为0,并增加总和和其他元素,那么就有可能保持解。
>>> possible
[[], None, [2], [3], None, [2, 3], None, [7], [8], [2, 7], [10], [3, 8]]