给定一张 m m m行 n n n列的地图由0和1表示,0表示可以走,1表示不能走。起点坐标与终点坐标分别为 ( x 1 , y 1 ) (x_1,y_1) (x1,y1)与 ( x 2 , y 2 ) (x_2,y_2) (x2,y2)。以地图左上角为原点,坐标为 ( 0 , 0 ) (0,0) (0,0)。求从起点到终点最少需要转几次弯及所对应的路径。
class Point(object):
def __init__(self, x, y):
self.__x = x
self.__y = y
def __add__(self, other):
return Point(self.__x + other.__x, self.__y + other.__y)
def __sub__(self, other):
return Point(self.__x - other.__x, self.__y - other.__y)
def __eq__(self, other):
return self.__x == other.__x and self.__y == other.__y
def get_x(self):
return self.__x
def get_y(self):
return self.__y
class Graph(object):
def __init__(self, row, column, default=None, graph=None):
self.__row = row
self.__col = column
if graph is None:
self.__graph = [[default for _ in range(column)] for _ in range(row)]
else:
self.__graph = list(graph)
def get(self, point):
return self.__graph[point.get_y()][point.get_x()]
def set(self, point, value):
self.__graph[point.get_y()][point.get_x()] = value
def get_row(self):
return self.__row
def get_column(self):
return self.__col
class BreadFirstPaths(object):
def __init__(self, graph, start, end):
self.__graph = graph
self.__start = start
self.__end = end
self.__min_corners = Graph(graph.get_row(), graph.get_column(), float('inf'))
self.__min_corners.set(start, 0)
self.__edge_to = Graph(graph.get_row(), graph.get_column())
self.__marked = Graph(graph.get_row(), graph.get_column(), False)
self.__marked.set(start, True)
self.__direction_vectors = [Point(1, 0), Point(-1, 0), Point(0, 1), Point(0, -1)]
self.__directions = Graph(graph.get_row(), graph.get_column())
self.__fringe = [start]
self.bfs()
def bfs(self):
result_found = False
while self.__fringe and not result_found:
point = self.__fringe.pop(0)
for direction_vector in self.__direction_vectors:
if self.goto(point, direction_vector):
result_found = True
break
return False
def reachable(self, point):
if not (0 <= point.get_x() < self.__graph.get_column() and 0 <= point.get_y() < self.__graph.get_row()) \
or self.__graph.get(point) == 1:
return False
return True
def goto(self, point, direction_vector):
next_point = point + direction_vector
direction = abs(direction_vector.get_x())
corners = self.__min_corners.get(point)
if self.__directions.get(point) is not None:
if direction != self.__directions.get(point):
corners += 1
else:
corners = 0
while self.reachable(next_point):
if corners < self.__min_corners.get(next_point):
if not self.__marked.get(next_point):
self.__fringe.append(next_point)
self.__marked.set(next_point, True)
self.__edge_to.set(next_point, point)
self.__directions.set(next_point, direction)
self.__min_corners.set(next_point, corners)
if next_point == self.__end:
return True
next_point += direction_vector
return False
def get_min_corners(self):
return self.__min_corners.get(self.__end)
def get_path(self):
path = []
point = self.__end
while point.get_x() != self.__start.get_x() or point.get_y() != self.__start.get_y():
path.insert(0, (point.get_x() + 1, point.get_y() + 1))
point = self.__edge_to.get(point)
path.insert(0, (self.__start.get_x() + 1, self.__start.get_y() + 1))
return path
m, n = 4, 5
graph_list = [[0, 0, 1, 0, 0], [1, 0, 0, 0, 1], [0, 0, 1, 0, 1], [0, 1, 0, 0, 0]]
x1, x2, y1, y2 = 0, 2, 0, 3
bfp = BreadFirstPaths(Graph(m, n, None, map_list), Point(x1, y1), Point(x2, y2))
shortest = bfp.get_min_corners()
if shortest != float('inf'):
print(shortest)
print(bfp.get_path())
else:
print('路径不存在')