Python广度优先搜索矩阵打印路径

时间:2017-11-08 10:52:21

标签: python matrix stack breadth-first-search

我有这行代码测试是否有一个在矩阵表示的迷宫中找到的路径。在我确定是否存在路径之后,如何在最后打印路径。我尝试过堆叠,但我不确定如何继续。

from queue import Queue
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])
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] = "2"
    if row+1 < numrows and matrix[row+1][col] == "0":
         q.put((row+1, col))
         matrix[row+1][col] = "3"
    if 0 <= col-1 and matrix[row][col-1] == "0":
         q.put((row, col-1))
         matrix[row][col-1] = "4"
    if 0 <= row-1 and matrix[row-1][col] == "0":
         q.put((row-1, col))
         matrix[row-1][col] = "5" 
row,col=numrows-1,numcols-1
var=matrix[row][col]
if var=="0":
    print ("There is no path.")
else:
    print ("There is a path.")

以下是一个示例矩阵:

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

3 个答案:

答案 0 :(得分:1)

因为您正在使用BFS来查找路径,所以最终方法不能是从起点到终点的最短路径,实际上,您只能得到哪个点连接到起点的结果。 / p>

因此,要获得精确路径,您可以使用DFS查找路径并使用堆栈来保存所访问的点,或使用Dijkstra找到从起点到终点的最短路径。

这是一个简单的DFS函数,它使用递归,路径用字符2表示

<?php

$host_name  = "hostname";
$database   = "database";
$user_name  = "username";
$password   = "pass";

$connect = mysqli_connect($host_name, $user_name, $password, $database);

$select = "SELECT username from userstasker";

$result = $connect->query($select);
$rows = array();

while($r = mysqli_fetch_assoc($result)) {
    $rows[] = $r;
}

echo json_encode($rows);

$connect->close();
?>

答案 1 :(得分:1)

这是一种通过从出口向后追踪路径来查找路径的相当简单的方法。您可以通过将移动保存到堆栈来撤消此操作。

为了便于查看,我稍微更改了代码,将N,S,E,W放在矩阵中(北,南,东,西)。要将这些方向字母解码为(行,列)步骤,我使用字典。

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!')

<强>输出

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!

答案 2 :(得分:1)

作为@程名锐的帖子的变种,DFS的这种实现也将返回它找到的第一个路径。作为一般性建议,如果您不关心最佳路径,DFS通常会比BFS更好地为您服务。

请注意,我们还必须确保不要在圈子中运行,因为此图表不是树。

# 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!")

打印:

[(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)]

路径首选项right -> left -> down -> up遇到的DFS的第一个(但肯定不是最短的)正确路径。