Dijkstra算法最短路径可视化(新)

内容还是比较详细的,这里不废话了,代码里都有

注意的是,绿色线尽头的点是:起点到达该点的最短距离

算法会寻找每个点临近点中最近的点,排除掉已经访问过的点

(matplotlib坏了还没修好,暂时用的cv2绘制)

python 复制代码
import math
import cv2
import numpy as np


class Dj:
    def __init__(self, points, start, end):
        self.points, self.start, self.end = points, start, end
        self.w, self.h = 1000, 600
        self.image = np.zeros((self.h, self.w, 3), dtype=np.uint8)
        self.route = []
        self.generate_map()
        self.video = cv2.VideoWriter("output.mp4", cv2.VideoWriter_fourcc(*'XVID'), 1, (self.w, self.h))  # 录制

    def generate_map(self):
        for p in self.points:
            cv2.circle(self.image, p, 10, (0, 0, 255), - 1)
            for ps in self.points[p]:
                cv2.line(self.image, p, ps, (255, 255, 255), 4)

    def line_shortest(self, p1, p2):
        cv2.line(self.image, p1, p2, (0, 255, 0), 4)
        return p2

    def line_route(self):
        for i in range(1, len(self.route) - 1):
            cv2.line(self.image, self.route[i - 1], self.route[i], (0, 255, 255), 4)

    def distance(self, point1, point2):
        return math.sqrt((point1[0] - point2[0]) ** 2 + (point1[1] - point2[1]) ** 2)

    # Dijkstra算法实现
    def dijkstra(self):
        dist = {point: float('inf') for point in self.points}  # 点:起点到当前点的最短距离
        dist[self.start] = 0  # 起点到自身距离设为0
        prev = {point: None for point in self.points}  # 记录每个点的前驱节点,用于回溯最短路径
        visited = set()  # 以及访问过的点
        while len(visited) < len(self.points):  # 未访问所有点
            frame = self.image.copy()
            current = None  # 到达的当前点为None
            min_dist = float("inf")  # 对于全部点,起点到达该点的最短距离
            # ########################################### 更新起点到当前点的所经过的最短路径(总距离) 和 当前点
            for point in points:  # 对于每个点
                if point not in visited and dist[point] < min_dist:  # 如果未访问,且起点到当前点的距离小于全局最短距离
                    min_dist = dist[point]  # 更新全局最短距离
                    current = point  # 更新到达的点

            visited.add(current)  # 在目前距离最优的情况下,该点已访问
            ##############################################
            if current == self.end:
                break  # 如果到达的点是终点,结束
            # ############################################# 更新起点到当前点相邻点中最近的点,和 到达距离
            for neighbor in points[current]:  # 对于当前点的所有相邻点
                new_dist = dist[current] + self.distance(current, neighbor)  # 更新起点到当前点的相邻点的总距离
                color = (255, 0, 0)
                if new_dist < dist[neighbor]:  # 如果这个距离是起点到该点相邻点的最短距离
                    dist[neighbor] = new_dist  # 更新起点到达该点相邻点的最短距离
                    prev[neighbor] = current
                    color = (0, 255, 0)
                    self.line_shortest(current, neighbor)  # 在原图上绘制到达该点的最短路径
                if neighbor in visited:  # 避免画回头的线
                    continue
                cv2.line(frame, neighbor, current, color, 4)  # 绘制临近点的路径
                cv2.waitKey(1000)
                ##############################################
                cv2.imshow("dj", frame)
                self.video.write(frame)
        cv2.imshow('dj', self.image)
        self.video.write(self.image)
        cp = self.end
        self.route = [cp]
        while cp:
            self.route.append(prev[cp])
            cp = prev[cp]
        cv2.waitKey(1000)
        self.line_route()
        cv2.imshow('dj', self.image)
        self.video.write(self.image)
        self.video.release()

        key = cv2.waitKey()
        if key == 27:  # 如果按下ESC键(ASCII码值为27),退出循环
            cv2.destroyAllWindows()
        return dist


# points = {
#     (0, 0): [(0, 200), (200, 300), (400, 100)],
#     (0, 200): [(200, 300), (0, 0)],
#     (200, 300): [(0, 200), (0, 0), (500, 500)],
#     (400, 100): [(0, 0), (500, 500)],
#     (500, 500): [(200, 300), (400, 100)],
# }
# 点与其相邻点
points = {
    (0, 0): [(400, 0), (0, 200), (500, 300)],
    (400, 0): [(0, 0), (700, 100)],
    (0, 200): [(0, 0), (300, 350)],
    (300, 350): [(0, 200), (400, 500)],
    (400, 500): [(300, 350), (600, 600)],
    (600, 600): [(400, 500), (500, 300), (1000, 600)],
    (500, 300): [(0, 0), (700, 100), (1000, 250), (600, 600)],
    (700, 100): [(400, 0), (500, 300), (1000, 250)],
    (1000, 250): [(700, 100), (500, 300), (900, 400)],
    (900, 400): [(1000, 250), (1000, 600)],
    (1000, 600): [(1000, 250), (600, 600)]

}
d = Dj(points, (0, 0), (1000, 600))
d.dijkstra()
相关推荐
z2005093038 分钟前
每日简单算法题——————跟着卡尔
算法
scan7241 小时前
智能体多个工具调用
python
2401_867623981 小时前
CSS Flex布局中如何设置子元素间距_掌握gap属性的现代用法
jvm·数据库·python
即使再小的船也能远航2 小时前
【Python】安装
开发语言·python
weixin_421725262 小时前
Linux 编程语言全解析:C、C++、Python、Go、Rust 谁更强?
linux·python·go·c·编程语言
没有梦想的咸鱼185-1037-16632 小时前
AI-Python机器学习、深度学习核心技术与前沿应用及OpenClaw、Hermes自动化编程
人工智能·python·深度学习·机器学习·chatgpt·数据挖掘·数据分析
️是782 小时前
信息奥赛一本通—编程启蒙(3395:练68.3 车牌问题)
数据结构·c++·算法
Liangwei Lin2 小时前
LeetCode 118. 杨辉三角
算法·leetcode·职场和发展
计算机安禾2 小时前
【c++面向对象编程】第24篇:类型转换运算符:自定义隐式转换与explicit
java·c++·算法
鼠鼠我(‘-ωก̀ )好困2 小时前
leetGPU
算法