我如何将以下递归dp转换为迭代

时间:2016-02-25 19:33:35

标签: python recursion dynamic-programming

我正在尝试将以下递归代码转换为自下而上/迭代动态编程。 但是我无法弄清楚我应该迭代的顺序,因为状态依赖于下一个和上一个索引。

matrix = [[-1, 4, 5, 1],
      [ 2,-1, 2, 4],
      [ 3, 3,-1, 3],
      [ 4, 2, 1, 2]]
rows = len(matrix)
cols = len(matrix[0])
cache = {}

def maxsum(dir, x, y):
   key = (dir, x, y)
   if key in cache: return cache[key]
   base = matrix[y][x]
   if x < cols-1:
       best = base + maxsum(2, x+1, y)
   else:
       best = base
   if dir != 0 and y > 0:
       best = max(best, base + maxsum(1, x, y-1))
   if dir != 1 and y < rows-1:
       best = max(best, base + maxsum(0, x, y+1))
   cache[key] = best
   return best

是否可以将此代码转换为迭代? 如果是,请帮我解决迭代的顺序。

'dir'可以取0-2的值。

x和y将介于1和1000之间。

我不想用堆栈来解决这个问题。我想用一般的迭代循环解决这个问题,就像我们在自下而上的动态编程中一样。

1 个答案:

答案 0 :(得分:1)

一般的想法是想象递归调用图/树和叶节点是什么;然后,迭代解决方案只是从叶节点开始,迭代地构建树,一直到根。

当然,这说起来容易做起来难,但通常问题的结构可以帮助你的直觉。在这种特殊情况下,这是2D网格。

直觉

让我们从建立一些直觉开始吧。查看代码中的分支。他们决定你是否在特定情况下递归。它们对应的是什么? 你什么时候不递言?按顺序,这些是:

  • 网格的右边缘
  • 网格的上边缘
  • 网格的下边缘

我们需要先建立这些。

基础案例

问问自己:在什么情况下我们根本没有递减?这是基本情况。没有特别的顺序,这些是:

  • 网格的右上角和main()
  • 网格的右下角和dir=1

递归案例

最后,问问自己:从我们拥有的值开始,我们可以计算什么?

  • 对于右上角,我们可以计算dir=0
  • 的整个右边缘
  • 对于右下角,我们可以计算dir=1
  • 的整个右边缘

然后,我们可以计算dir=0的整个右边缘。

现在我们已经填充了右边缘的值,我们可以计算出什么呢?记住上面的特殊情况。 依赖于右边缘的单元格是位于右边缘左侧的顶部和底部边缘中的两个单元格,分别为dir=2dir=1

有了这个,我们现在可以计算dir=0dir=1右侧的第二列,因此dir=0

重复,直到找到所需单元格的值。

代码

注意:这有点不理想,因为它填满整个表格,但它应该足以说明这个想法。

dir=2