初学最短路算法

这几天自学了最短路的


Bellman_Ford和Dijkstra算法,通过一道简单题来回顾一下。

题目来源HDU1874.

Problem Description
某省自从实行了很多年的畅通工程计划后,终于修建了很多路。不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。

现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。
 


Input
本题目包含多组数据,请处理到文件结束。
每组数据第一行包含两个正整数N和M(0<N<200,0<M<1000),分别代表现有城镇的数目和已修建的道路的数目。城镇分别以0~N-1编号。
接下来是M行道路信息。每一行有三个整数A,B,X(0<=A,B<N,A!=B,0<X<10000),表示城镇A和城镇B之间有一条长度为X的双向道路。
再接下一行有两个整数S,T(0<=S,T<N),分别代表起点和终点。
 


Output
对于每组数据,请在一行里输出最短需要行走的距离。如果不存在从S到T的路线,就输出-1.
 


Sample Input
3 3 0 1 1 0 2 3 1 2 1 0 2 3 1 0 1 1 1 2
 


Sample Output
2 -1
解一:Dijkstra算法
#include <cstdio> #include <iostream> #include <cstring> #include <string> #include <cmath> #include <queue> #include <set> #include <stack> #include <algorithm> #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define mem(a) memset(a, 0, sizeof(a)) #define eps 1e-5 #define M 100005 #define INF 99999 using namespace std; int vis[10006]; int a,b; int d[M],w[1005][1005];//d记录从起点到I的最短距离,w[I][j]表示i到j的距离// int st,en; void Dij() { int v; for(int i=0;i<a;i++) { d[i]=w[st][i];//记录di// } d[st]=0;//起点到起点的距离为0// vis[st]=1;//标记起点// for(int i=0;i<a;i++)////循环每个点// { int tmp=INF; for(int j=0;j<a;j++)//找到离这个点最近且没被访问的点// { if(tmp>d[j]&&!vis[j]) { tmp=d[j]; v=j; } } vis[v]=1//标记这个点// for(int k=0;k<a;k++) { if(!vis[k]) { d[k]=min(d[k],d[v]+w[v][k]);//比较从起点直接到k点和起点经过v点到k点的大小// } } } } int main() { while(cin>>a>>b) { mem(vis); mem(d); mem(w); for(int i=0;i<202;i++) { for(int j=0;j<202;j++) { w[i][j]=INF;//首先不知道I到J的距离,将其视为无穷大,后面,没有i到j的直达路线的话,也是无穷大// w[i][i]=0; } } for(int i=0;i<b;i++) { int aa,bb,cc; cin>>aa>>bb>>cc; if(w[aa][bb]>cc) { w[aa][bb]=cc;//正确记录i到j的距离// w[bb][aa]=cc; } } cin>>st>>en; Dij(); if(d[en]<INF) { cout<<d[en]<<endl; } else { cout<<"-1"<<endl; } } }
解二:Bellman_Ford算法
#include <cstdio> #include <iostream> #include <cstring> #include <string> #include <cmath> #include <queue> #include <set> #include <stack> #include <algorithm> #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define mem(a) memset(a, 0, sizeof(a)) #define eps 1e-5 #define M 100005 #define INF 0x3f3f3f3f using namespace std; struct node { int a,b,c; }d[2000]; int aa,bb,st,en; int dis[M]; void BF(int x,int y) { for(int i=0;i<aa;i++) { dis[i]=INF;//起点到i点的距离是无穷大// } dis[st]=0; for(int i=0;i<aa-1;i++)//循环aa-1个点// { for(int j=0;j<2*bb;j++) { if(dis[d[j].b]>dis[d[j].a]+d[j].c)//判断从起点到b和起点经过a点到b点大小// { dis[d[j].b]=dis[d[j].a]+d[j].c; } } } if(dis[en]==INF) { cout<<"-1"<<endl; } else { cout<<dis[en]<<endl; } } int main() { while(cin>>aa>>bb) { int w,e,r; for(int i=0;i<bb;i++) { cin>>w>>e>>r; d[i].a=w; d[i].b=e; d[i].c=r; d[i+bb].a=e; d[i+bb].b=w; d[i+bb].c=r; } cin>>st>>en; BF(st,en); } }
资源下载链接为: https://pan.quark.cn/s/9e7ef05254f8 行列式是线性代数的核心概念,在求解线性方程组、分析矩阵特性以及几何计算中都极为关键。本教程将讲解如何用C++实现行列式的计算,重点在于如何输出分数形式的结果。 行列式定义如下:对于n阶方阵A=(a_ij),其行列式由主对角线元素的乘积,按行或列的奇偶性赋予正负号后求和得到,记作det(A)。例如,2×2矩阵的行列式为det(A)=a11×a22-a12×a21,而更高阶矩阵的行列式可通过Laplace展开或Sarrus规则递归计算。 在C++中实现行列式计算时,首先需定义矩阵类或结构体,用二维数组存储矩阵元素,并实现初始化、加法、乘法、转置等操作。为支持分数形式输出,需引入分数类,包含分子和分母两个整数,并提供与整数、浮点数的转换以及加、减、乘、除等运算。C++中可借助std::pair表示分数,或自定义结构体并重载运算符。 计算行列式的函数实现上,3×3及以下矩阵可直接按定义计算,更大矩阵可采用Laplace展开或高斯 - 约旦消元法。Laplace展开是沿某行或列展开,将矩阵分解为多个小矩阵的行列式乘积,再递归计算。在处理分数输出时,需注意避免无限循环和除零错误,如在分数运算前先约简,确保分子分母互质,且所有计算基于整数进行,后再转为浮点数,以避免浮点数误差。 为提升代码可读性和可维护性,建议采用面向对象编程,将矩阵类和分数类封装,每个类有明确功能和接口,便于后续扩展如矩阵求逆、计算特征值等功能。 总结C++实现行列式计算的关键步骤:一是定义矩阵类和分数类;二是实现矩阵基本操作;三是设计行列式计算函数;四是用分数类处理精确计算;五是编写测试用例验证程序正确性。通过这些步骤,可构建一个高效准确的行列式计算程序,支持分数形式计算,为C++编程和线性代数应用奠定基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值