【问题标题】:More on dynamic programming更多关于动态规划
【发布时间】:2016-02-18 21:13:28
【问题描述】:

两周前,我在这里发布了THIS 关于动态编程的问题。用户Andrea Corbellini 准确地回答了我想要的,但我想更进一步地解决这个问题。

这是我的功能

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,2,3,4,5 ] )

上一个问题解决了计算最优值的问题。现在, 而不是为上面的例子计算最优值 33,我想打印我们得到最优解的方式(最优解的路径)。所以,我想打印列表被剪切/划分的索引,以列表的形式获得最佳解决方案。所以,上面例子的答案是:

[ 3,2,1,4 ](在第三个标记/索引处切割极点/列表,然后在第二个索引之后,然后在第一个索引之后,最后在第四个索引处)。 那就是答案应该是列表的形式。列表的第一个元素将是列表的第一次切割/分割应该在最佳路径中发生的索引。第二个元素将是列表的第二个切割/除法,依此类推。

也可以有不同的解决方案:

[ 3,4,2,1 ] 

它们仍然会引导您获得正确的输出。因此,您打印哪一个并不重要。但是,我不知道如何跟踪和打印动态编程解决方案所采用的最佳路径。 顺便说一句,我想出了一个非递归的解决方案来解决我之前的问题中解决的问题。但是,我仍然无法确定打印最佳解决方案的路径。这是上一个问题的非递归代码,可能有助于解决当前问题。

def Opt(numbers):
prefix = [0]
for i in range(1,len(numbers)+1):
    prefix.append(prefix[i-1]+numbers[i-1])
results = [[]]
for i in range(0,len(numbers)):
    results[0].append(0)
for i in range(1,len(numbers)):
    results.append([])
    for j in range(0,len(numbers)):
        results[i].append([])
for i in range(2,len(numbers)+1): # for all lenghts (of by 1)
    for j in range(0,len(numbers)-i+1): # for all beginning
        results[i-1][j] = results[0][j]+results[i-2][j+1]+prefix[j+i]-prefix[j]
        for k in range(1,i-1): # for all splits
            if results[k][j]+results[i-2-k][j+k+1]+prefix[j+i]-prefix[j] < results[i-1][j]:
                results[i-1][j] = results[k][j]+results[i-2-k][j+k+1]+prefix[j+i]-prefix[j]
return results[len(numbers)-1][0]

【问题讨论】:

  • 这就像一篇博文。你有什么问题?
  • 值得一提的是,找到动态规划解决方案的“路径”比仅仅找到解决方案要困难得多。
  • @cat 如何按照我的解释更改算法的输出
  • @TheTask1337 您的“问题”不仅隐藏在不必要的文字墙中,无法帮助我理解为什么要阅读此内容,而且问题陈述本身对于本地人来说几乎是不可理解的扬声器。请尝试准确指出您需要帮助的内容,并进行解释,以便不经意的观察者可以了解发生了什么。
  • @cat 管理员重新整理了我的问题后,可能会更清楚。不过谢谢。

标签: python dynamic-programming memoization


【解决方案1】:

这是打印所选内容的一种方式:

我在您之前的问题中使用了@Andrea Corbellini 提供的记忆化递归解决方案。如下所示:

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

现在,我们有了所有元组的缓存值,包括选定的元组。

使用它,我们可以打印选择的元组,如下所示:

selectedList = []
def printSelected (n, low):

    if len(n) == 1:
        # No need to print because it's 
        # already printed at previous recursion level.
        return

    minVal = math.Inf
    minTupleLeft = ()
    minTupleRight = ()
    splitI = 0

    for i in range(1, len(n)):
        tuple1ToI = tuple (n[:i])
        tupleiToN = tuple (n[i:])

        if (cache[tuple1ToI] + cache[tupleiToN]) < minVal:
            minVal = cache[tuple1ToI] + cache[tupleiToN]
            minTupleLeft = tuple1ToI
            minTupleRight = tupleiToN
            splitI = low + i


    print minTupleLeft, minTupleRight, minVal
    print splitI   # OP just wants the split index 'i'.
    selectedList.append(splitI) # or add to the list as requested by OP

    printSelected (list(minTupleLeft), low)
    printSelected (list(minTupleRight), splitI)

你调用上面的方法如下所示:

printSelected (n, 0)

【讨论】:

  • 谢谢,但它并不能完全满足我的要求。问题出在 line: print n[ splitI ] 我想要剪切的位置,而不是剪切的元素。所以我尝试将其更改为: print n.index( n[splitI] ) 但问题是,它与原始列表无关,因为当函数递归调用自身时,原始列表拆分并且我们没有关于它的信息了。所以对于输入 [ 7,6,5,4,3,2,1 ] 输出可能是例如: [2, 1, 4, 3, 5, 6] 但我只能得到: [ 2,1,2 ,1,1,1 ] 它工作正常,但它没有做我想要的。谢谢
  • 好的。我可以修复那部分。我不清楚你想要什么。我会更新并通知你。
  • 谢谢,但是请注意输入可以包含多个唯一的数字,所以输入也可以是例如[1,4,14,12,3,4,5,3] .
  • 我已经更新了答案。现在,它跟踪索引。一旦你尝试这个就更新我。我将索引附加到 selectedList。
猜你喜欢
  • 2011-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-07
  • 1970-01-01
  • 2021-04-02
相关资源
最近更新 更多