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()
相关推荐
Lill_bin1 分钟前
分页查询在数据库中的好处
java·开发语言·数据库·python·oracle·性能优化
在西湖雾雨中起舞8 分钟前
题目 1738: 排序
算法
在西湖雾雨中起舞11 分钟前
题目 2794: 求平均年龄
数据结构·c++·算法
呆呆在发呆.32 分钟前
数据结构复习总结(期末前更新)
数据结构·c++·算法·链表·贪心算法·柔性数组
极客小张43 分钟前
基于STM32的智电表系统课题设计思路:python友好界面、ADC、UART串口、数据分析
c语言·python·stm32·单片机·数据分析·毕业设计·课程设计
cloud___fly1 小时前
力扣hot100——双指针
数据结构·算法·leetcode·贪心算法
勤劳的进取家1 小时前
利用模拟退火算法求解旅行商问题
开发语言·python
威威猫的栗子1 小时前
用 Python Turtle 绘制经典汤姆猫:重温卡通角色的经典魅力
开发语言·python
一念之坤1 小时前
11篇--图像边缘检测
图像处理·python·opencv·计算机视觉
工一木子1 小时前
【Leecode】Leecode刷题之路第82天之删除排序链表中的重复元素II
java·数据结构·算法·leetcode·链表