打印动态编程解决方案中遍历的路径

时间:2015-04-04 14:12:27

标签: algorithm graph path state dynamic-programming

问题很简单:在典型的动态编程解决方案中,如何打印在计算最终解决方案期间遍历的实际状态?

让我试着在一个例子的帮助下解释我到底需要什么 -

假设我们有一个问题的DP解决方案,其中每个州都有二维,即解决方案中的状态看起来像(i,j)。现在,我们有一个起始状态 (0,0)和一些最终状态(i,n),其中i从0变为n。

因此,典型的解决方案将如下工作:

Start from a starting state: in this case -> (0,0)
Move to the next state based on some computation: suppose from (0,0), we could go to (1,0), (1,1) or (1,2).
.
.
Keep on traversing until we reach one of the end states: in this case (i,n), for any i.

现在,我需要打印此解决方案中遍历的路径。基本上,如果我可以找出从哪个状态到达最终状态,我可以使用该逻辑返回起始状态并因此打印路径。

P.S。:如果问题看起来太明显,请道歉。

1 个答案:

答案 0 :(得分:2)

  1. 您可以在计算过程中显式存储此信息。也就是说,除DP(i, j)之外,您可以保存PARENT(i, j),它表示我们来自的状态以获取(i, j)的结果(并在初始计算期间进行转换时正确更新它)。

  2. 有时,我们可以在不明确存储的情况下计算PARENT(i, j)。情况是这样的:

    • 有可能弄清楚我们可以从哪些状态转换到当前状态。

    • 我们可以检查转换是否为我们提供了此状态的最佳解决方案。

  3. 当我们知道每个州的父级时,我们可以从最终状态开始迭代,将每个州添加到列表中,然后继续到其父级,直到我们到达开始状态(并在必要时最后反转列表) )。我们也可以递归地做同样的事情。

    这是一个(可能是微不足道的)例子:

    让我们假设我们正在解决一个标准问题:给定一个带有数字的网格,如果我们只允许向右或向下移动,找到从左上角到右下角的路径,最大总和。

    明确计算父母(我在这里省略了角落案例):

    if dp(i - 1, j) > dp(i, j - 1) then
        dp(i, j) = a(i, j) + dp(i - 1, j)
        par(i, j) = (i - 1, j)
    else
        dp(i, j) = a(i, j) + dp(i, j - 1)
        par(i, j) = (i, j - 1)
    

    隐式:

    let getPar(i, j)
        if dp(i - 1, j) > dp(i, j - 1)
            return (i - 1, j)
        return (i, j - 1)
    

    对于更复杂的问题,这个想法是一样的。