首页 > 编程语言 >Dijkstra算法的应用(算法思想)

Dijkstra算法的应用(算法思想)

时间:2024-12-01 20:59:26浏览次数:5  
标签:currentNode int 路径 Dijkstra 算法 edge 过路费 应用 节点

有了一张自驾旅游路线图,你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径。

输入格式:
输入说明:输入数据的第 1 行给出 4 个正整数 n、m、s、d,其中 n(2≤n≤500)是城市的个数,顺便假设城市的编号为 0~(n−1);m 是高速公路的条数;s 是出发地的城市编号;d 是目的地的城市编号。随后的 m 行中,每行给出一条高速公路的信息,分别是:城市 1、城市 2、高速公路长度、收费额,中间用空格分开,数字均为整数且不超过 500。输入保证解的存在。

输出格式:
在一行里输出路径的长度和收费总额,数字间以空格分隔,输出结尾不能有多余空格。

该题适用于Dijkstra算法,Dijkstra算法是一种用于寻找图中单源最短路径的经典算法。适用于没有负权边的图。本题除了寻找从出发点到目的地之间的最短路径,还要在多条最短路径中选择总费用最低的一条。
本题算法思想如下:

  1. 初始化:为每个结点设置初始的距离值,初始的过路费值,为每个结点设置一个前驱节点,创建一个访问标记数组,用于记录被处理过的结点;
  2. 主循环:每次迭代中,从未访问的结点中选择一个距离最小的结点,将该节点标记为已访问。更新该节点的所有邻居节点的距离和过路费,此时,如果通过当前节点到达邻居节点的新路径比已知路径更短,更新邻居节点的距离和过路费,并更新前驱节点;如果新节点与一直路径长度相同但是过路费更低,则更新邻居节点的过路费,并更新前驱节点。
  3. 终止 :当所有结点都被访问过,或者目标节点已经被访问时,算法终止。
  4. 输出:通过前驱节点数组回溯路径,输出从起点到终点的最短路径,总距离和过路费。

以下为完整代码:

#include <iostream>
#include <vector>
#include <queue>
#include <limits>

using namespace std;

const int INF = 1000000;  // 定义一个很大的数表示无穷大

struct Edge {
    int to;       // 目标城市
    int distance; // 高速公路长度
    int toll;     // 过路费
};

// 比较器,用于优先队列
struct CompareCost {
    bool operator()(const pair<int, int>& left, const pair<int, int>& right) {
        if (left.first == right.first) {
            return left.second > right.second; // 如果总成本相同,比较过路费
        }
        return left.first > right.first; // 否则,比较总成本
    }
};

void dijkstra(const vector<vector<Edge>>& graph, int start, int end) {
    int n = graph.size();
    vector<int> dist(n, INF);  // 最短距离
    vector<int> cost(n, INF);  // 最低过路费
    vector<int> prev(n, -1);   // 前驱节点
    vector<bool> visited(n, false);  // 访问标记

    dist[start] = 0;
    cost[start] = 0;

    // 优先队列
    priority_queue<pair<int, int>, vector<pair<int, int>>, CompareCost> pq;
    pq.push({0, start});  // (total cost, current node)

    while (!pq.empty()) {
        auto [totalCost, currentNode] = pq.top();
        pq.pop();

        if (visited[currentNode]) continue;

        visited[currentNode] = true;

        for (const auto& edge : graph[currentNode]) {
            int newDistance = dist[currentNode] + edge.distance;
            int newToll = cost[currentNode] + edge.toll;
            int newTotalCost = newDistance + newToll;

            if (newDistance < dist[edge.to]) {
                dist[edge.to] = newDistance;
                cost[edge.to] = newToll;
                prev[edge.to] = currentNode;
                pq.push({newTotalCost, edge.to});
            } else if (newDistance == dist[edge.to] && newToll < cost[edge.to]) {
                cost[edge.to] = newToll;
                prev[edge.to] = currentNode;
                pq.push({newTotalCost, edge.to});
            }
        }
    }

    // 输出结果
    if (dist[end] == INF) {
        cout << "No path found" << endl;
    } else {
        cout << dist[end] << " " << cost[end] << endl;
    }
}

int main() {
    int n, m, s, d;
    cin >> n >> m >> s >> d;

    vector<vector<Edge>> graph(n);

    for (int i = 0; i < m; ++i) {
        int u, v, length, toll;
        cin >> u >> v >> length >> toll;
        graph[u].push_back({v, length, toll});
        graph[v].push_back({u, length, toll});  // 无向图
    }

    dijkstra(graph, s, d);

    return 0;
}

标签:currentNode,int,路径,Dijkstra,算法,edge,过路费,应用,节点
From: https://www.cnblogs.com/yuncloud517/p/18580334

相关文章

  • 敏捷算法
    敏捷开发方法是一种软件开发方法论,旨在通过迭代、灵活性和协作来应对需求的不断变化,以及快速交付高质量的软件产品。下面对极限编程(XP)、水晶法(Crystal)、并列争球法(Scrum)和自适应软件开发(ASD)这四种常见的敏捷开发方法进行详细分析:1.极限编程(XP)极限编程(ExtremeProgramming,简......
  • AES加密算法原理详解
    AES加密:高级加密标准(AES,AdvancedEncryptionStandard)为最常见的对称加密算法(微信小程序加密传输就是用这个加密算法的)。对称加密算法也就是加密和解密用相同的密钥,具体的加密流程如下图:明文p::::info没有经过加密的数据。:::密钥K::::info用来加密明文的密码,在......
  • 51单片机从入门到精通:理论与实践指南综合应用——实战篇(七)
    学完了入门篇和常用资源篇,接下来就进入了综合篇——实战篇了。大概是三个案例,写三篇博客给大家讲解,希望可以帮助大家。在生活的道路上,每一个人都会遇到挑战与困难,这些时刻或许会让前路显得模糊不清,甚至让人感到无助和迷茫。但请记住,正是这些艰难的时光塑造了更加坚强、更有智......
  • 使用WebAssembly结合Rust实现高性能Web应用的技术详解
    ......
  • 数字信号处理实验报告六:数字信号处理在多音频拨号系统中的应用
    一、实验目的与实验意义通过对多音频拨号系统的分析与仿真实验,了解双音多频信号的产生、检测,包括对双音多频信号进行DFT时的参数选择等,使学生初步了解数字信号处理在实际中的使用方法和重要性。二、实验原理及方法关于双音多频拨号系统   双音多频(DualToneMultiFreq......
  • <a>元素的应用
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><title>超链接</title></hea......
  • python学习笔记(15)算法(8)双向队列
    在队列中,我们仅能删除头部元素或在尾部添加元素。双向队列(double‑endedqueue)提供了更高的灵活性,允许在头部和尾部执行元素的添加或删除操作。一、双向队列常用操作队首入队(push_front):在双向队列的头部添加一个元素。队首出队(pop_front):删除双向队列头部的元素。队尾入队(push......
  • python学习笔记(12)算法(5)迭代与递归
    一、迭代迭代(iteration)是一种重复执行某个任务的控制结构。在迭代中,程序会在满足一定的条件下重复执行某段代码,直到这个条件不再满足。迭代通常用于解决需要逐步推进的计算问题,例如遍历数组、计算阶乘等。迭代的优点是内存使用效率高,易于优化,适合处理大规模数据。1.for循环......
  • 【知识】图论 朱刘算法梳理
    朱刘算法:树形图的定义:以某一个点为根的有向树,被称为树形图一个有向图,满足无环且每个点的入度为\(1\)(除了根节点),被称为树形图最小树形图:对于所有树形图中,找到一个总权值和最小的树形图,被称为最小树形图。最小树形图问题本质上其实就是有向图上的最小生成树问题。......
  • 游戏防检查之易语言鼠标轨迹算法 - 模拟人工轨迹
    一.简介鼠标轨迹算法是一种模拟人类鼠标操作的程序,它能够模拟出自然而真实的鼠标移动路径。鼠标轨迹算法的底层实现采用C/C++语言,原因在于C/C++提供了高性能的执行能力和直接访问操作系统底层资源的能力。鼠标轨迹算法具有以下优势:模拟人工轨迹:算法能够模拟出非贝塞尔曲线......