Python breadth-first search matrix print path

前端 未结 3 1855
深忆病人
深忆病人 2021-01-23 23:16

I have this line of code that tests wether or not there is a path to be found in a labyrinth represented by a matrix. How do I print the path at the end after I\'ve determined w

相关标签:
3条回答
  • 2021-01-23 23:56

    As a variant to @程名锐's post, this implementation of a DFS will also return the first path it has found. And as a general advice, if you don't care about the path being optimal, a DFS will usually serve you better than a BFS.

    Note that we also have to make sure not to run in circles, since this graph is not a tree.

    # for convenience
    matrix = [
        ["0", "0", "0", "0", "1", "0", "0", "0"],
        ["0", "1", "1", "0", "1", "0", "1", "0"],
        ["0", "1", "0", "0", "1", "0", "1", "0"],
        ["0", "0", "0", "1", "0", "0", "1", "0"],
        ["0", "1", "0", "1", "0", "1", "1", "0"],
        ["0", "0", "1", "1", "0", "1", "0", "0"],
        ["1", "0", "0", "0", "0", "1", "1", "0"],
        ["0", "0", "1", "1", "1", "1", "0", "0"]
    ]
    num_rows = len(matrix)
    num_cols = len(matrix[0])
    
    # just to be a bit more flexible, could also be passed as a function argument
    goal_state = (num_rows - 1, num_cols - 1)
    
    
    def dfs(current_path):
        # anchor
        row, col = current_path[-1]
        if (row, col) == goal_state:
            return True
    
        # try all directions one after the other
        for direction in [(row, col + 1), (row, col - 1), (row + 1, col), (row - 1, col)]:
            new_row, new_col = direction
            if (0 <= new_row < num_rows and 0 <= new_col < num_cols and  # stay in matrix borders
                    matrix[new_row][new_col] == "0" and                  # don't run in walls
                    (new_row, new_col) not in current_path):             # don't run in circles
                # try new direction
                current_path.append((new_row, new_col))
                if dfs(current_path):  # recursive call
                    return True
                else:
                    current_path.pop()  # backtrack
    
    
    # result a list of coordinates which should be taken in order to reach the goal
    result = [(0, 0)]
    if dfs(result):
        print("Success!")
        print(result)
    else:
        print("Failure!")
    

    Prints:

    [(0, 0), (0, 1), (0, 2), (0, 3), (1, 3), (2, 3), (2, 2), (3, 2), (3, 1), (3, 0), (4, 0), (5, 0), (5, 1), (6, 1), (6, 2), (6, 3), (6, 4), (5, 4), (4, 4), (3, 4), (3, 5), (2, 5), (1, 5), (0, 5), (0, 6), (0, 7), (1, 7), (2, 7), (3, 7), (4, 7), (5, 7), (6, 7), (7, 7)]
    

    The first (but for sure not shortest) correct path a DFS with the pathing preferences right -> left -> down -> up encounters.

    0 讨论(0)
  • 2021-01-24 00:01

    Because you are using BFS to find the path, the final approach cannot be the shortest path from the start point to the finish point, and actually, you can only get the result that which point is connected to the start point.

    So, to get an exact path, you may use DFS to find a path and use a stack to save the points visited or use Dijkstra to find the shortest path from the start point to the finish point.

    Here is a simple DFS function which uses recursion and the path is represented in character 2

    suc = 0
    
    def dfs(row, col):
        global suc
        if suc == 1:
            return
        matrix[row][col] = "2"
    
        if (row, col) == (numrows - 1, numcols - 1):
            print("Success")
            suc = 1
    
        if col + 1 < numcols and matrix[row][col + 1] == "0":
            dfs(row, col + 1)
    
        if row + 1 < numrows and matrix[row + 1][col] == "0":
            dfs(row + 1, col)
    
        if 0 <= col - 1 and matrix[row][col - 1] == "0":
            dfs(row, col - 1)
    
        if 0 <= row - 1 and matrix[row - 1][col] == "0":
            dfs(row - 1, col)
    
    
    maze = open(input())
    matrix = maze.readlines()
    matrix = [i.strip() for i in matrix]
    matrix = [i.split() for i in matrix]
    numrows, numcols = len(matrix), len(matrix[0])
    
    dfs(0, 0)
    
    var = matrix[numrows - 1][numcols - 1]
    
    for m in matrix:
        print(m)
    
    if var == "0":
        print("There is no path.")
    else:
        print("There is a path.")
    
    0 讨论(0)
  • 2021-01-24 00:10

    Here's a fairly simple way to find the path, by tracing it backwards from the exit. You can reverse this by saving the moves to a stack.

    To make it easier to see, I've changed your code slightly to put N, S, E, W in the matrix (for North, South, East, West). To decode those direction letters to (row, column) steps I use a dictionary.

    from queue import Queue
    
    maze='''\
    0 0 0 0 1 0 0 0
    0 1 1 0 1 0 1 0
    0 1 0 0 1 0 1 0
    0 0 0 1 0 0 1 0
    0 1 0 1 0 1 1 0
    0 0 1 1 0 1 0 0
    1 0 0 0 0 1 1 0
    0 0 1 1 1 1 0 0
    '''
    
    def show(matrix):
        for line in matrix:
            print(*line)
        print()
    
    matrix=maze.splitlines()
    matrix=[i.strip() for i in matrix]
    matrix=[i.split() for i in matrix]
    numrows, numcols = len(matrix), len(matrix[0])
    
    show(matrix)
    
    q=Queue()
    row=0
    col=0
    q.put((row,col))
    while not q.empty():
        row, col = q.get()
        if col+1 < numcols and matrix[row][col+1] == "0":
             q.put((row, col+1))
             matrix[row][col+1] = "W"
        if row+1 < numrows and matrix[row+1][col] == "0":
             q.put((row+1, col))
             matrix[row+1][col] = "N"
        if 0 <= col-1 and matrix[row][col-1] == "0":
             q.put((row, col-1))
             matrix[row][col-1] = "E"
        if 0 <= row-1 and matrix[row-1][col] == "0":
             q.put((row-1, col))
             matrix[row-1][col] = "S" 
    row,col=numrows-1,numcols-1
    var=matrix[row][col]
    
    show(matrix)
    
    if var=="0":
        print ("There is no path.")
        exit()
    else:
        print ("There is a path.")
    
    # Trace the path
    step = {'N': (-1, 0), 'S': (1, 0), 'E': (0, 1), 'W': (0, -1)}
    while True:
        print((row, col), 'go', var)
        if row == 0 and col == 0:
            break
        r, c = step[var]
        row += r
        col += c
        var = matrix[row][col]
    
    print('Home!')
    

    output

    0 0 0 0 1 0 0 0
    0 1 1 0 1 0 1 0
    0 1 0 0 1 0 1 0
    0 0 0 1 0 0 1 0
    0 1 0 1 0 1 1 0
    0 0 1 1 0 1 0 0
    1 0 0 0 0 1 1 0
    0 0 1 1 1 1 0 0
    
    E W W W 1 S W W
    N 1 1 N 1 S 1 N
    N 1 E N 1 S 1 N
    N W W 1 S W 1 N
    N 1 N 1 S 1 1 N
    N W 1 1 S 1 E N
    1 N W W W 1 1 N
    E N 1 1 1 1 E N
    
    There is a path.
    (7, 7) go N
    (6, 7) go N
    (5, 7) go N
    (4, 7) go N
    (3, 7) go N
    (2, 7) go N
    (1, 7) go N
    (0, 7) go W
    (0, 6) go W
    (0, 5) go S
    (1, 5) go S
    (2, 5) go S
    (3, 5) go W
    (3, 4) go S
    (4, 4) go S
    (5, 4) go S
    (6, 4) go W
    (6, 3) go W
    (6, 2) go W
    (6, 1) go N
    (5, 1) go W
    (5, 0) go N
    (4, 0) go N
    (3, 0) go N
    (2, 0) go N
    (1, 0) go N
    (0, 0) go E
    Home!
    
    0 讨论(0)
提交回复
热议问题