实验三 -2 使用Dijkstra算法求解最小总费用

本文介绍了如何使用Dijkstra算法解决最小总费用问题,涉及实验目的、实验内容、设备环境、实验步骤、设计思想和算法流程。通过编程实现,解决N个人在N个车站间的公交费用优化问题。
摘要由CSDN通过智能技术生成

使用Dijkstra算法求解最小总费用

目录

使用Dijkstra算法求解最小总费用

一、实验目的及要求

二、实验内容

三、实验设备与环境

四、实验设计方案

(一)实验步骤:

(二)设计思想:

(三)算法描述或开发流程:

五、实验结果

六、附录源码


一、实验目的及要求

1.理解最小费用问题(Dijkstra算法)的基本概念及其在图论中的应用。

2.掌握Dijkstra算法的实现,能够解决给定的问题。

3.掌握如何使用数据结构和算法解决实际问题,提高编程能力和问题解决能力。

二、实验内容

编写程序,求解最小费用问题(Dijkstra)。问题描述:假设有N个车站(车站的编号为1到N)和N个人,首先所有人均在车站1,将这N个人分派到N个车站去,每一个分派到一个车站,这些人只能乘坐公交车,每条单向公交车连接连个车站并且有一定的费用;接着这N个人又回到车站1,求最小总花费。

测试数据:

4 6

1 2 10

2 1 60

1 3 20

3 4 10

2 4 5

4 1 50

三、实验设备与环境

1.Windows 11

2.Codeblocks

四、实验设计方案

(一)实验步骤:

1.定义图的数据结构,包括节点和边。节点表示车站和人,边表示公交车连接关系和费用。

2.初始化Dijkstra算法所需的距离数组,将所有距离初始化为无穷大,将起点(车站1)的距离初始化为0。

3.使用Dijkstra算法进行求解,从起点开始,按照距离的递增顺序遍历所有节点。

4.对于每个节点,更新其相邻节点的距离,选择最小费用路径。

5.重复步骤4,直到所有节点都被访问过或无法找到更短路径为止。

6.输出最小总花费和对应的分派方案。

(二)设计思想:

1.使用优先队列(堆)来存储待访问节点,按照距离的递增顺序访问节点,实现Dijkstra算法的关键步骤。

2.使用邻接矩阵或邻接表来表示图,方便存储节点之间的连接关系和费用。

3.在更新距离时,要注意处理边的权重(费用),确保选择最小费用路径。

4.使用动态规划的思想来逐步计算最小总花费,避免重复计算。

(三)算法描述或开发流程:

1.定义图的数据结构:使用邻接矩阵或邻接表来表示图,每个节点表示一个车站或一个人,边表示公交车连接关系和费用。

2.初始化Dijkstra算法:创建一个距离数组dist[]和一个标记数组visited[],将所有距离初始化为无穷大(如INT_MAX),将起点(车站1)的距离初始化为0。将所有节点标记为未访问(false)。

3.遍历节点:使用优先队列(堆)来存储待访问节点,按照距离的递增顺序访问节点。循环执行以下步骤,直到所有节点都被访问过或无法找到更短路径为止。
        3.1 从优先队列中取出距离最小的节点u,标记为已访问(true)。
        3.2  遍历节点u的所有相邻节点v(即边(u, v)):如果v未被访问过,并且通过u到达v的距离小于当前已知的距离dist[v],则更新dist[v]为通过u到达v的距离,并将v加入优先队列。
        3.3 将u的所有相邻节点v标记为已访问(true)。

4.输出结果:遍历完所有节点后,dist[]数组中存储的就是从起点到各个节点的最小距离。根据问题的要求,输出最小总花费和对应的分派方案。

五、实验结果

六、附录源码

#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;

const int MAXN = 1005;
const int INF = 0x3f3f3f3f;

int n, m; // n为车站数量,m为边数
vector<pair<int, int> > edge; // 存储每条边的起点和终点以及费用
int dist[MAXN]; // 存储到达每个车站的最小费用
int vis[MAXN]; // 标记每个车站是否被访问过

void dijkstra(int start) {
    memset(dist, INF, sizeof(dist));
    memset(vis, 0, sizeof(vis));
    dist[start] = 0;
    priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > pq;
    pq.push(make_pair(0, start));
    while (!pq.empty()) {
        int u = pq.top().second;
        pq.pop();
        if (vis[u]) continue;
        vis[u] = 1;
        for (int i = 0; i < edge.size(); i++) {
            int v = edge[i].first;
            int w = edge[i].second;
            if (!vis[v] && dist[v] > dist[u] + w) {
                dist[v] = dist[u] + w;
                pq.push(make_pair(dist[v], v)); // 这里应该使用 '>' 而非 '>>'
            }
        }
    }
}

int main() {
    cin >> n >> m;
    edge.clear();
    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        edge.push_back(make_pair(v, w)); // 将边加入到edge中,并按照边的终点进行排序
    }
    dijkstra(1); // 从车站1开始求解最小费用问题
    int ans = 0;
    for (int i = 2; i <= n; i++) {
        ans += dist[i]; // 将每个人分派到各个车站,并累加总费用
    }
    cout << ans << endl; // 输出最小总花费
    return 0;
}

 

  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

噗-噗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值