c++ - 在网格中找到最佳路径的最大长度

标签 c++ algorithm recursion dynamic-programming

给定一个N*N的网格,现在我们需要找到一条最大长度的好路径,好路径定义如下:

  1. 好的路径总是从标记为 0 的单元格开始
  2. 我们只能向左、向右、向上或向下移动
  3. 如果第 i 个单元格的值为 A,则路径中下一个单元格的值必须为 A+1。

现在给定这几个条件,我需要找出可以走的最大路径的长度。我还需要计算最大长度的路径。

例子:设 N=3,我们有 3*3 矩阵如下:

0 3 2               
3 0 1               
2 1 0            

那么这里的最大好路径长度是3,这样好路径的数量是4。

0 3 2
3 0 1
2 1 0

0 3 2
3 0 1
2 1 0

0 3 2
3 0 1
2 1 0

0 3 2
3 0 1
2 1 0

最佳答案

此问题是 Longest Path Problem 的变体,但是您的限制使这个问题变得容易得多,因为该图实际上是一个 Directed Acyclic Graph (DAG) , 因此该问题是可以有效解决的。

定义有向图 G=(V,E) 如下:

  • V = { 矩阵中的所有单元格}(完整性检查:|V| = N^2)
  • E = { (u,v) | u 与 v 相邻且 value(u) + 1 = value(v)

请注意,上面定义的结果图是一个 DAG,因为你不能有任何循环,因为它会导致有一些边 e= (u,v) 这样 值(u) > 值(v)

现在,你只需要找到longest path in a DAG从任何起点。这是由 topological sort 完成的在图上,然后使用动态规划:

init:
for every source in the DAG:
D(v) = 0            if value(v) = 0
       -infinity    otherwise
step:
for each node v from first to last (according to topological sort)
   D(v) = max{D(u) + 1 | for each edge (u,v) }

完成后,找到具有最大值D(v) 的节点v,这是最长“好路径”的长度。
找到路径本身是通过重新滚动上面的过程来完成的,从最大 D(v) 向后追溯你的步骤,直到你回到值为 0 的初始节点。

这种方法的复杂度是 O(V+E) = O(n^2)


由于您正在寻找最长路径的数量,因此您可以稍微修改此解决方案以计算到达每个节点的路径数量,如下所示:

Topological sort the nodes, let the sorted array be arr (1)
For each node v from start to end of arr:
   if value(v) = 0:
        set D(v) = 1 
   else
        sum = 0
        for each u such that (u,v) is an edge: (2)
            sum = sum + D(u) 
        D(v) = sum

以上将为每个节点v 找到到达它的“好路径”D(v) 的数量。您现在要做的就是找到具有总和节点 v 的最大值 x 使得 value(v) = xD(v) > 0,将到达任意节点的路径数与value(v)相加:

max = 0
numPaths = 0
for each node v:
    if value(v) == max:
         numPaths = numPaths + D(v)
    else if value(v) > max AND D(v) > 0:
         numPaths = D(v)
         max = value(v)
return numPaths

注意事项: (1) - “常规”排序在这里起作用,但需要 O(n^2logn) 时间,而拓扑排序需要 O(n^2) 时间
(2) 提醒,(u,v) 是一条边,如果: (1) uv 相邻 (2) value(u) + 1 = 值(v)

关于c++ - 在网格中找到最佳路径的最大长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28397368/

相关文章:

algorithm - 维基百科的广度优先搜索示例 : How is a parentless node reached?

c - 使用递归查找序列

c++ - 迭代 vector 不会更新对象

c++ - 我可以将 vector 作为initial_sum和其他函数传递给std::accumulate吗?

python - 列表在合并排序的递归循环中创建后返回无类型

algorithm - 查找给定纬度和经度坐标的州

java - 二叉树/递归 (Java)(更新)

PHP:从递归函数返回一个数组

c++ - 让 freeglut 库与 opengl 一起工作

c++ - Apache C++ 模块持久全局对象