问题描述
我正在尝试解决此问题:
有一个带有r行和c列的网格。坐在左上方单元格中的机器人只能向左右两个方向移动。但是必须避免某些单元格,并且机器人无法踩踏它们。从左上角到右下角找到机器人的路径。
这个问题专门要求一条路,这似乎很简单:
将网格设为boolean[][]
,我拥有的伪代码为
List<String> path = new ArrayList<String>()
boolean found = false
void getPath(r,c){
if (!found) {
if ( (r or c is outofbounds) || (!grid[r][c]) )
return
if (r==0 AND c==0) // we reached
found = true
getPath(r-1,c)
getPath(r,c-1)
String cell = "(" + r + "," + c + ")"
path.add(cell)
}
}
尽管我想知道如何获得所有可能的路径(不仅是计数,而且还有路径值)。请注意,它具有r行和c列,因此它不是nxn网格。我试图考虑一个DP /递归解决方案,但无法提出任何建议并陷入困境。很难想到递归有两种方式。
有指针吗?此外,对于如何“思考”此类问题的任何常规帮助也将不胜感激:)。
解决方法
有指针吗?此外,对于如何“思考”此类问题的任何常规帮助也将不胜感激:)。
解决方法:
- 精神上构造问题的图形G。在这种情况下,顶点是网格中的单元,并在存在有效的机器人移动的位置创建有向边。
- 搜索G的属性。在这种情况下,G是 DAG (有向无环图)。
- 使用此类属性提出解决方案。在这种情况下(G是DAG),通常使用拓扑排序和动态编程查找有效路径的数量。
实际上,您不需要构造图,因为边缘集非常清晰,也可以进行拓扑排序,因为矩阵的常规迭代(增量行索引和列增量索引)是此隐式图的拓扑排序。
可以通过在每个单元格[x][y]
中存储从[0][0]
到[x][y]
的有效路径的数量并检查下一步要移动的位置来解决动态编程部分。
重复发生:
计算后,答案存储在dp[n - 1][m - 1]
中,其中n
是行数,m
是列数。总体运行时间为O(nm)
。
如何查找所有可能的有效路径:
通常的回溯都是可行的,我们可以通过早期修剪来加快速度。实际上,如果我们计算dp
矩阵,然后从像元[n - 1][m - 1]
进行回溯,则只要机器人进入dp
值为零的像元,就可以避免无效路径。
具有dp
矩阵的Python代码是预先计算的:
n,m = 3,4
bad = [[False,False,False],[ True,True,[False,False]]
dp = [[1,1,1],[0,2],3]]
paths = []
curpath = []
def getPath(r,c):
if dp[r][c] == 0 or r < 0 or c < 0:
return
curpath.append((r,c))
if r == 0 and c == 0:
paths.append(list(reversed(curpath)))
getPath(r - 1,c)
getPath(r,c - 1)
curpath.pop()
getPath(n - 1,m - 1)
print(paths)
# valid paths are [[(0,0),(0,1),2),3),(1,(2,3)],# [(0,3)]]
请注意,该代码与您的代码非常相似,因此需要将所有有效路径存储在一起,并注意附加列表是curpath
的副本,以免最后出现一个空列表。
运行时间:O((n + m) * (amount of valid paths))
,因为模拟的机器人移动属于有效路径,或者第一步是使用远见(dp
)检测到的无效路径。警告:由于有效路径的数量可以为,因此此方法是指数的。