当前位置: 首页 > 知识库问答 >
问题:

Python中的回溯路径问题

苏华荣
2023-03-14

最近,我发现了回溯,没有太多思考就从一个展示了一些数独回溯技巧的家伙那里开始了这本书(https://www.youtube.com/watch?v=G_UYXzGuqvM

这个问题被相应地表述为:使用回溯计算x*y网格中从左下角到右上角的所有路径的数量。这包括以下路径:https://imgur.com/3t3Np4M.请注意,每个点只能访问一次。编写一个函数np(x,y),返回x*y网格中的路径数。例如,np(2,3)应该返回38。提示:创建一个布尔网格,在其中标记已访问的位置。

无论我在这段短代码中做了什么改变,我都不会接近38。

```
grid = [[0, 0,  0, 0,  0, 1],
        [0, 0,  0, 0,  0, 0],
        [0, 0,  0, 0,  0, 0],
        [1, 0,  0, 0,  0, 0]]

solution = 0
def number_of_paths(x, y):
    global solution
    global grid
    for i in range(0, x):
        for j in range(0, y):
            if grid[i][j] == 0:
                grid[i][j] = 1
                number_of_paths(x, y)
                grid[i][j] = 0
                solution += 1
    return




if __name__ == '__main__':
    number_of_paths(2, 3)
    print(grid)
    print(solution)```

这是一个带有数独解算器的示例解。

```
grid = [[5, 3, 0, 0, 7, 0, 0, 0, 0], 
       [6, 0, 0, 1, 9, 5, 0, 0, 0],
       [0, 9, 8, 0, 0, 0, 0, 6, 0],
       [8, 0, 0, 0, 6, 0, 0, 0, 3],
       [4, 0, 0, 8, 0, 3, 0, 0, 1],
       [7, 0, 0, 0, 2, 0, 0, 0, 6],
       [0, 6, 0, 0, 0, 0, 2, 8, 0],
       [0, 0, 0, 4, 1, 9, 0, 0, 5], 
       [0, 0, 0, 0, 8, 0, 0, 7, 9]]

import numpy as np

def possible(y, x, n):
    global grid
    for i in range(0, 9):
        if grid[y][i] == n:
            return False
    for i in range(0, 9):
        if grid[i][x] == n:
            return False
    x0 = (x // 3) * 3
    y0 = (y // 3) * 3
    for i in range(0, 3):
        for j in range(0, 3):
            if grid[y0 + i][x0 + j] == n:
                return False
    return True

def solve():
    global grid
    for y in range(9):
        for x in range(9):
            if grid[y][x] == 0:
                for n in range(1, 10):
                    if possible(y, x, n):
                        grid[y][x] = n
                        solve()
                        # backtracking - bad choice
                        grid[y][x] = 0
                return
    print(np,matrix(grid))
    input("More?")```

共有2个答案

郑晗日
2023-03-14

我将展示一个坐标系上的解决方案,其中(0,0)是左上角,(maxY,maxX)是右下角。向右移动会增加x,向下移动会增加y。
1-如果你试图解决图像中的精确迷宫,那么你的网格阵列形状是错误的。请注意,您在正方形的角之间移动,有4个点可以水平移动,3个点可以垂直移动
2-提示告诉您如何对访问状态使用布尔掩码,您已经有一个网格数组,因此不需要单独的数组
3-你的代码的主要问题是你如何在迷宫中前进。循环结构

for i in range(0, x):
        for j in range(0, y):

没有意义,因为当你处于一个位置(x,y),你只能在4个主要方向(右,上,左,下)移动。然而,这个循环让它看起来像是你试图进入你身后的所有位置,这是无效的。在我的代码中,我将明确地展示有关遍历的内容。

grid = [[0, 0, 0, 0],
        [0, 0, 0, 0],
        [1, 0, 0, 0]]


#  number of solutions
solution = 0


#  maximum values of x and y coordinates
maxX = len(grid[0])-1
maxY = len(grid)-1

#  endpoint coordinates, top(y=0) right(x=maxX) of the maze
endX = maxX
endY = 0

#  starting point coordinates, bottom(y=maxY) left(x=0) of the maze
mazeStartX = 0
mazeStartY = maxY

def number_of_paths(startX, startY):
    global solution
    global grid
    global mask
    
    
    #  if we reached the goal, return at this point
    if (startX == endX and startY == endY):
        solution += 1
        return
    
    
    #  possible directions are 
    #RIGHT (+1x, 0y)
    #UP (0x, -1y)
    #LEFT (-1x, 0y)
    #DOWN (0x, +1y)
    #  I use a direction array like this to avoid nested ifs inside the for loop
    dx = [1, 0, -1, 0]
    dy = [0, -1, 0, 1]
   
    for d in range(len(dx)):
        newX = startX + dx[d]
        newY = startY + dy[d]
        
        #  out of maze bounds
        if (newX < 0 or newY < 0):
            continue
        
        #  out of maze bounds
        if (newX > maxX or newY > maxY):
            continue
            
       
        if (grid[newY][newX] == 1):
            #  this are is already visited 
            continue
        else:
            #  branch from this point
            grid[newY][newX] = 1
            number_of_paths(newX, newY)
            grid[newY][newX] = 0


if __name__ == '__main__':
    number_of_paths(mazeStartX, mazeStartY)
    print(grid)
    print(solution)
汪臻
2023-03-14

一些建议:

  1. 您可能希望将一个集合用于网格,如果它不是集合的成员,则在访问它时立即添加一个正方形
  2. 计数器和网格可以是全局的,但一开始可能更容易将它们作为函数的参数。在解决方案更清晰之后,你可以担心这些细节
  3. 你处理这个问题的方式不对。最好有一个函数来计算从起点到终点的路径数(通过为尚未访问的邻居调用该函数。确保更新网格)。除此之外,您还可以有一个函数,该函数为起点和终点的每个组合调用路径函数。小贴士:你不必反向计算同一条路径!你可以有一张计算路径和的地图。如果相反的方向已经被计算过了,就不用麻烦了。之后,将路径数量加倍2

祝你好运

 类似资料:
  • 我正在编写一个python类来寻找8皇后问题的解决方案。如何在方法中正确实现回溯?我认为递归应该可以工作,但是,程序在第一次尝试没有找到解决方案后停止,回溯也不会发生。所有helper方法都能正常工作。 我的问题是在添加女王之前缺少一个板子的深度副本,还是仅仅是缺少回溯?

  • 这是LeetCode的唯一路径问题https://leetcode.com/problems/unique-paths/. m x n网格上有一个机器人。机器人最初位于左上角(即网格[0][0])。机器人试图移动到右下角(即网格[m-1][n-1])。机器人只能在任何时间点向下或向右移动。 给定两个整数m和n,返回机器人到达右下角可能的唯一路径数。 这是来自教程杯的回溯解决方案https://ww

  • 一个位于XxX网格左上角的机器人正试图到达右下角。机器人可以向上、向下、向左或向右移动,但不能访问同一地点两次。右下角有多少条可能的唯一路径? 对此,快速算法解决方案是什么?我花了大量的时间试图找出一个快速算法来解决这个问题。但还是卡住了。 除了回溯之外,使用动态规划来处理唯一路径的快速算法解决方案是什么?可以快速找到10x10网格的结果1,568,758,030,464,750,013,214,

  • 问题内容: 代表Windows目录的最佳方法是什么?我一直在尝试修改脚本,但是它永远无法正常工作,因为我似乎无法正确获得目录,我想是因为它充当转义符? 问题答案: 183 你可以始终使用: 这适用于linux和Windows。其他可能性是 如果你对某些名称有疑问,也可以尝试使用原始字符串文字: 但是,最佳实践是使用始终为你的操作系统选择正确配置的模块功能: 从python 3.4开始,你还可以使用

  • 问题内容: 我正在运行Mac OS X环境,习惯于使用〜/提供对当前用户目录的访问。 例如,在我的python脚本中,我只是尝试使用 但是想用 尝试运行此文件或目录时出现错误消息。有任何想法吗? 问题答案: 您需要使用 正在当前工作目录中寻找名为“〜”的目录。 还请注意该函数的文档-特别是,您需要正确设置环境变量以确保进行扩展。在大多数情况下,这不会成为问题,但是如果不进行扩展,那可能就是原因。

  • 在二维上 1表示起始正方形。 2代表结束方块。 0代表我们可以走过的空方块。 -1代表我们无法跨越的障碍。 返回四向行走的次数 来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/unique-paths-iii 我正在尝试使用回溯模式来解决这个问题 这是我的代码 测试样本: 预期结果:2 结果: 0