【问题标题】:Dynamic programming doesn't give correct answer动态规划没有给出正确答案
【发布时间】:2016-02-06 16:54:18
【问题描述】:

我最近发现了一种叫做动态编程的技术,我偶然发现了一个我无法弄清楚的问题。一开始你会得到一个参数列表,你需要对它进行求和,就好像你正在切割它一样。如果列表只有一个元素,则不要对其求和。如果它有更多,则将元素相加并以各种可能的方式对其进行切割。因此,如果列表有 n 个元素,则只有 n-1 种方法可以对其进行剪切。图片说明:

我首先想总结所有可求和的部分,我期望结果为 20( 11 + 9 )(甚至认为正确答案是 9 ),但我认为这将是一个好的开始。但是我的代码返回数字 37,我不知道为什么。我做错了什么?

summ = 0

def Opt( n ):
    global summ

    if len( n ) == 1:
        return 0
    else:
        summ += sum( n )
        for i in range( 1,len( n ) ):
            summ += Opt( n[ :i ] ) + Opt( n[ i: ] )

        return summ

print( Opt( [ 1,2,3 ] ) )

感谢您的宝贵时间和任何回答!

【问题讨论】:

  • 你为什么使用全局?
  • 另外,Opt 到底应该做什么?图片真的没有帮助。我认为某处应该有一个min()(“最低和”),但我对您的问题理解得不够好,无法提出答案
  • 在我的代码中 Opt 应该返回 20(如果列表有多个元素,则剪切列表并将它们相加)
  • 编写一个全局变量并同时返回它肯定既没有必要也无助于清楚地表达代码背后的想法。

标签: python dynamic-programming


【解决方案1】:

我想这就是你想要的:

def Opt(n):
    if len(n) == 1:
        return 0
    else:
        return sum(n) + min(Opt(n[:i]) + Opt(n[i:])
                            for i in range(1, len(n)))

例子:

>>> Opt([1])
0
>>> Opt([1, 2])
3
>>> Opt([2, 3])
5
>>> Opt([1, 2, 3])
9
>>> Opt([1, 2, 3, 4])
19

动态编程是将“大问题”分解成小的子问题。

因此,首先,您应该确定大问题与子问题之间的关系。您可以通过编写递归关系来做到这一点。在这种情况下:

Opt(nums) = sum(nums) + min(...)

你还需要一个起点:

Opt(nums) = 0 iff len(nums) == 1

如您所见,一旦编写了递归关系,将其转换为 Python 代码通常很简单。

了解每个子问题都是独立的,不需要外部输入,这一点很重要。您对global 变量的使用不仅产生了错误的结果,而且违背了动态编程的精神。

您使用树来表达Opt() 很好。您忘记做的是编写每个节点与其子节点之间的关系。如果你这样做了,我几乎可以肯定你自己会找到正确的解决方案。

我们还没有完成(感谢Stefan Pochmann 的关注)。为了构建真正的动态规划解决方案,您还需要避免多次解决同一个问题。目前,运行Opt([1,2,3,4]) 会导致多次调用Opt([1,2])。防止这种情况的一种方法是使用记忆:

cache = {}

def Opt(n):
    # tuple objects are hashable and can be put in the cache.
    n = tuple(n)

    if n in cache:
        return cache[n]

    if len(n) == 1:
        result = 0
    else:
        result = sum(n) + min(Opt(n[:i]) + Opt(n[i:])
                              for i in range(1, len(n)))

    cache[n] = result
    return result

对了,记得处理n为空的情况(即len(n) == 0)。

【讨论】:

  • 这不是动态编程,因为您要一遍又一遍地解决子问题,而不仅仅是一次。
  • @StefanPochmann:你是对的!我忘记了最重要的部分!更新答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-25
  • 2015-06-23
  • 1970-01-01
  • 1970-01-01
  • 2019-03-07
相关资源
最近更新 更多