目录

Python实例题

题目

要求:

解题思路:

代码实现:

Python实例题

题目

基于 Dijkstra 算法的地图导航系统

要求

  • 实现一个简单的地图导航系统,使用 Dijkstra 算法计算最短路径。
  • 支持以下功能:
    • 加载地图数据(节点和边)
    • 计算两点之间的最短路径
    • 可视化地图和路径
    • 支持不同的权重计算方式(距离、时间、费用)
  • 添加用户交互界面,允许用户选择起点和终点。

解题思路

  • 使用邻接表表示地图图结构。
  • 实现 Dijkstra 算法计算最短路径。
  • 使用 NetworkX 和 Matplotlib 进行地图可视化。

代码实现

import networkx as nx
import matplotlib.pyplot as plt
import heapq

class MapGraph:
    def __init__(self):
        self.graph = nx.Graph()
    
    def add_node(self, node_id, label=None, pos=None):
        """添加地图节点"""
        self.graph.add_node(node_id, label=label or str(node_id), pos=pos)
    
    def add_edge(self, node1, node2, weight=1, **kwargs):
        """添加地图边"""
        self.graph.add_edge(node1, node2, weight=weight, **kwargs)
    
    def dijkstra(self, start, end, weight='weight'):
        """Dijkstra算法实现"""
        distances = {node: float('inf') for node in self.graph.nodes}
        distances[start] = 0
        
        priority_queue = [(0, start)]
        previous_nodes = {node: None for node in self.graph.nodes}
        
        while priority_queue:
            current_dist, current_node = heapq.heappop(priority_queue)
            
            if current_node == end:
                break
            
            if current_dist > distances[current_node]:
                continue
            
            for neighbor in self.graph.neighbors(current_node):
                weight_val = self.graph[current_node][neighbor].get(weight, 1)
                distance = current_dist + weight_val
                
                if distance < distances[neighbor]:
                    distances[neighbor] = distance
                    previous_nodes[neighbor] = current_node
                    heapq.heappush(priority_queue, (distance, neighbor))
        
        # 构建路径
        path = []
        current_node = end
        
        while current_node is not None:
            path.append(current_node)
            current_node = previous_nodes[current_node]
        
        path.reverse()
        
        if path[0] == start:
            return path, distances[end]
        else:
            return None, None
    
    def visualize(self, path=None, figsize=(10, 8)):
        """可视化地图和路径"""
        plt.figure(figsize=figsize)
        
        # 获取节点位置
        pos = nx.get_node_attributes(self.graph, 'pos')
        if not pos:
            pos = nx.spring_layout(self.graph)
        
        # 绘制节点
        nx.draw_networkx_nodes(
            self.graph, pos, 
            node_size=700, 
            node_color='lightblue', 
            edgecolors='black'
        )
        
        # 绘制节点标签
        labels = nx.get_node_attributes(self.graph, 'label')
        nx.draw_networkx_labels(self.graph, pos, labels, font_size=12)
        
        # 绘制边
        edge_weights = nx.get_edge_attributes(self.graph, 'weight')
        nx.draw_networkx_edges(
            self.graph, pos, 
            width=2, 
            edge_color='gray', 
            alpha=0.6
        )
        
        # 绘制边权重
        nx.draw_networkx_edge_labels(
            self.graph, pos, 
            edge_labels=edge_weights, 
            font_size=10
        )
        
        # 如果有路径,高亮显示
        if path and len(path) > 1:
            path_edges = [(path[i], path[i+1]) for i in range(len(path)-1)]
            
            nx.draw_networkx_edges(
                self.graph, pos, 
                edgelist=path_edges, 
                width=4, 
                edge_color='red', 
                alpha=0.8
            )
            
            # 高亮起点和终点
            nx.draw_networkx_nodes(
                self.graph, pos, 
                nodelist=[path[0]], 
                node_size=700, 
                node_color='green', 
                edgecolors='black'
            )
            
            nx.draw_networkx_nodes(
                self.graph, pos, 
                nodelist=[path[-1]], 
                node_size=700, 
                node_color='red', 
                edgecolors='black'
            )
        
        plt.axis('off')
        plt.title('地图导航系统')
        plt.tight_layout()
        plt.show()

def main():
    # 创建示例地图
    map_graph = MapGraph()
    
    # 添加节点(位置为(x, y)坐标)
    map_graph.add_node('A', '学校', (1, 3))
    map_graph.add_node('B', '医院', (3, 4))
    map_graph.add_node('C', '商场', (4, 2))
    map_graph.add_node('D', '公园', (2, 1))
    map_graph.add_node('E', '酒店', (5, 3))
    map_graph.add_node('F', '图书馆', (6, 1))
    
    # 添加边(距离、时间、费用)
    map_graph.add_edge('A', 'B', distance=2.5, time=10, cost=5)
    map_graph.add_edge('A', 'D', distance=2.0, time=8, cost=4)
    map_graph.add_edge('B', 'C', distance=1.8, time=7, cost=3)
    map_graph.add_edge('B', 'E', distance=3.0, time=12, cost=6)
    map_graph.add_edge('C', 'E', distance=2.2, time=9, cost=4)
    map_graph.add_edge('C', 'F', distance=1.5, time=6, cost=3)
    map_graph.add_edge('D', 'F', distance=4.0, time=15, cost=7)
    map_graph.add_edge('E', 'F', distance=2.8, time=11, cost=5)
    
    print("地图节点:")
    for node_id, data in map_graph.graph.nodes(data=True):
        print(f"{node_id}: {data['label']}")
    
    # 用户交互
    while True:
        print("\n请选择导航模式:")
        print("1. 最短距离")
        print("2. 最短时间")
        print("3. 最低费用")
        print("4. 查看地图")
        print("5. 退出")
        
        choice = input("请输入选项 (1-5): ")
        
        if choice == '5':
            break
        
        if choice == '4':
            map_graph.visualize()
            continue
        
        if choice not in ['1', '2', '3']:
            print("无效的选项,请重新输入。")
            continue
        
        weight_map = {'1': 'distance', '2': 'time', '3': 'cost'}
        weight_type = weight_map[choice]
        weight_name = {'distance': '距离', 'time': '时间', 'cost': '费用'}[weight_type]
        
        start_node = input("请输入起点节点 (A-F): ").upper()
        end_node = input("请输入终点节点 (A-F): ").upper()
        
        if start_node not in map_graph.graph.nodes or end_node not in map_graph.graph.nodes:
            print("无效的节点,请重新输入。")
            continue
        
        path, total_cost = map_graph.dijkstra(start_node, end_node, weight=weight_type)
        
        if path:
            print(f"\n最短{weight_name}路径:")
            path_str = " -> ".join([map_graph.graph.nodes[node]['label'] for node in path])
            print(f"{path_str}")
            print(f"总{weight_name}: {total_cost}")
            
            # 可视化路径
            map_graph.visualize(path)
        else:
            print(f"无法找到从 {start_node} 到 {end_node} 的路径。")

if __name__ == "__main__":
    main()
Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐