算法学习--Day9
继上一次完成最小生成树后,这次我开始准备最短路径的程序。
最短路分为两种算法,第一个为Floyd算法,第二个为Dijkstra。
简单来说,Floyd是以点为参照对象,它使用三层循环求解当前图中所有点之间的最短距离。
也就是说,当他的循环处理结束后,你就可以从中找到任意两点之间的最短路径了。
他将大规模问题简化成为若干个子问题,并先对规模小的问题求解出最优值,之后利用规模小的问题的解去递推出大规模问题的解。
核心代码:
for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ for(int k=1;k<=n;k++){ if(ans[j][i]==-1 || ans[i][k]==-1) continue; //这句话说明倘若我j-i-k中间有某条路是不通的,这个时候我就不能被更新,所以直接跳过就好 if(ans[j][k]==-1 || ans[j][i]+ans[i][k]<ans[j][k]){ ans[j][k]= ans[j][i]+ans[i][k];} //这句话用来更新最小值 } } }
下面我们看dijkstra算法。
题目描述
给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
输入描述:
输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点t。n和m为0时输入结束。 (1<n<=1000, 0<m<100000, s != t)
输出描述:
输出 一行有两个数, 最短距离及其花费。
// // Created by 陈平 on 2018/6/7. // #include "iostream" #include "stdio.h" #include "vector" using namespace std; struct E{ int next; int c; int cost; }; vector<E> edge[1001]; int dis[1001]; int cost[1001]; bool mark[1001]; int main(){ int n,m; int s,t; while (scanf("%d%d",&n,&m)!=EOF){ if(n==0 && m==n) break; for (int i = 1; i <=n ; ++i) { edge[i].clear(); } while (m--){ int a,b,c,cost; cin>>a>>b>>c>>cost; E tmp; tmp.c = c; tmp.cost = cost; tmp.next = b; edge[a].push_back(tmp); tmp.next = a; edge[b].push_back(tmp); } cin>>s>>t; for (int j = 1; j <=n ; ++j) { dis[j] = -1; mark[j] = false; } dis[s] = 0; cost[s] = 0; mark[s] = true; int newP = s; for (int k = 1; k <n ; ++k) { for (int i = 0; i <edge[newP].size() ; ++i) { int t = edge[newP][i].next; int c = edge[newP][i].c; int co = edge[newP][i].cost; if(mark[t]) continue; if (dis[t]==-1 || dis[t]>dis[newP] + c ||dis[t]==dis[newP] + c && cost[t]>cost[newP]+co ){ dis[t] = dis[newP] + c; cost[t] = cost[newP] + co; } } int minn = 1000000; for (int j = 1; j <=n ; ++j) { if(mark[j]) continue; if(dis[j]==-1) continue; if(dis[j] < minn ){ minn = dis[j]; newP = j; } } mark[newP] = true; } cout<<dis[t]<<" "<<cost[t]<<endl; } }
在写最短路的时候,我们要熟悉使用链表的写法,当数据量增多的时候,使用链表会使节省空间与时间。所以我们要在初始化的时候使用push_back函数把值push进去。而在处理的时候,我们需要分两步去找最优解。第一步为更新当前点集合所连接的点的长度数据。(因为上一步加入了另一个点后我们的长度还未更新)第二步为寻找未在当前集合并且是最短距离的点。(具体流程见我之前的一个博客——https://www.cnblogs.com/Pinging/p/7911169.html)
因为菜,所以仍在努力。