当前位置: 首页 > 知识库问答 >
问题:

用动态规划求子集和

艾仲渊
2023-03-14

我正在练习动态编程,我正在努力调试我的代码。这个想法是在给定一组数字的情况下找出求和是否可能。这是我的代码:

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]

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

共有1个答案

唐弘益
2023-03-14

如果只提供正值,我不太明白为什么需要二维列表。您可以简单地使用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)的每个值是否可以构造它。因此,如果可能的[sum]True,则可以构造sum

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

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

所以值02357891011可与硬币一起构造。

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

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,用<代码>5,用<代码>2,3,等等来构造。

 类似资料:
  • 我有一个子集问题的工作代码,如果它发现一个子集等于所需的目标,它可以打印数字。 > 我想打印给定目标的所有可能的子集,我不知道要为此更改什么。 我如何让它对负数起作用?

  • 给定一个数组,是否可以从起始索引开始选择一组整数,这样该组就与给定的目标相加?但是,附加的限制是必须选择所有的6。 groupSum6(0,[5,6,2],8)true groupSum6(0,[5,6,2],9)false groupSum6(0,[5,6,2],7)false 只是想弄清楚我错在哪里。声明nums[start]==6的特殊情况是不是错误的方法?

  • 我正在为动态编程编写一些复习材料。我需要提出如何划分子问题,计算出基本情况,并提出递归公式。 给定 n 个正整数 a1,a2,...,an、一个数字 k 和一个目标 W,我们希望选择一个子集 T,其总和恰好是 k 个元素,其总和最接近 W。每个元素只能选择一次。定义一个具有 3 个参数的子问题(即 C[x,y,z] = ...)。 我只处理过几个动态编程示例,从未处理过定义子问题时需要3个参数的示

  • 我无法弄清楚重叠子问题的DP第一属性在哪里适合子集和问题。然而,我理解最优子结构部分。在执行包含和排除元素的递归解决方案时,问题在哪里重叠 是不是因为这是一个NP问题,所以没有DP的两个性质 问题的链接是http://www.geeksforgeeks.org/dynamic-programming-subset-sum-problem/ 有人能帮助我理解这一点吗。

  • 问题链接如下: https://www.geeksforgeeks.org/dynamic-programming-subset-sum-problem/ 我没有看到重叠的子问题属性在问题中得到满足,至少在输入情况下是如此。例如,在下面的链接中,递归树没有任何重叠的子问题 http://www.zrzahid.com/subset-sum-problem-dynamic-programming/

  • 给定一组非负整数和一个值和,确定给定集合中是否有和等于给定和的子集。 例如: 我实际上用这段代码解决了问题: 然而,现在我想重建所有可能的组合,形成给定的总和。 是可以从我的回忆录矩阵中做到这一点,还是我必须以不同的方式做到这一点?