最省力的路径

  给定一张 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('路径不存在')
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值