日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

信息学奥赛一本通 1342:【例4-1】最短路径问题

發(fā)布時(shí)間:2025/3/17 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 信息学奥赛一本通 1342:【例4-1】最短路径问题 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

【題目鏈接】

ybt 1342:【例4-1】最短路徑問題

【題目考點(diǎn)】

1. 圖論 最短路徑

圖中有V個(gè)頂點(diǎn)E條邊,最短路徑算法時(shí)間復(fù)雜度:

  • 樸素Dijkstra算法:O(V2)O(V^2)O(V2)
  • Dijkstra堆優(yōu)化算法:O(ElogE)O(ElogE)O(ElogE)
  • SPFA算法:一般情況下O(kE)O(kE)O(kE),k為頂點(diǎn)平均入隊(duì)次數(shù),最壞情況下O(VE)O(VE)O(VE)
  • Floyd算法: O(V3)O(V^3)O(V3)

空間復(fù)雜度:

  • 鄰接矩陣:O(V2)O(V^2)O(V2)
  • 鄰接表:O(V+E)O(V+E)O(V+E)

【解題思路】

該題輸入各頂點(diǎn)坐標(biāo),以及每條邊是哪兩個(gè)點(diǎn)相連。那么需要我們手動計(jì)算兩點(diǎn)間距離,作為這條邊的權(quán)值。使用兩點(diǎn)間距離公式:(x1,x2)(x_1,x_2)(x1?,x2?)(y1,y2)(y_1,y_2)(y1?,y2?)的距離
(x1?x2)2+(y1?y2)2\sqrt{(x_1-x_2)^2+(y_1-y_2)^2}(x1??x2?)2+(y1??y2?)2?
建圖完成后,就是一個(gè)標(biāo)準(zhǔn)的求最短路徑問題。
注意:表示距離的數(shù)組,邊的權(quán)值,在該問題中都是double類型的。
double類型的數(shù)組dis,將元素都設(shè)為大約為1.08?10161.08*10^{16}1.08?1016的較大值,可以寫memset(dis, 0x43, sizeof(dis));
該題頂點(diǎn)數(shù)目為100,那么邊最多10000個(gè)。用哪種算法及存儲結(jié)構(gòu)都可以。
該題頂點(diǎn)個(gè)數(shù)較少,可以使用Floyd算法及鄰接矩陣。本題主要展示最短路徑算法使用鄰接矩陣時(shí)的寫法。
如想看鄰接表的寫法,可以參考我在同一章節(jié)下其他題目的題解。

【題解代碼】

解法1:Floyd算法+鄰接矩陣

#include<bits/stdc++.h> using namespace std; #define N 105 struct Cord {int x, y; }; double edge[N][N]; int n, m, st, te;//st:起點(diǎn) te:終點(diǎn) double dis[N][N];//dis[i][j]:頂點(diǎn)i到頂點(diǎn)j的最短距離 Cord ver[N];//保存每個(gè)頂點(diǎn)的坐標(biāo) double getDis(Cord a, Cord b)//獲取點(diǎn)a到點(diǎn)b兩點(diǎn)間直線距離 {return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } void init() {int f, t;cin >> n;for(int i = 1; i <= n; ++i)cin >> ver[i].x >> ver[i].y;cin >> m;for(int i = 1; i <= m; ++i){cin >> f >> t;edge[f][t] = edge[t][f] = getDis(ver[f], ver[t]);//頂點(diǎn)f到頂點(diǎn)t的邊的權(quán)值為點(diǎn)f到點(diǎn)t的直線距離 }cin >> st >> te; } void floyd() {memset(dis, 0x43, sizeof(dis));//這樣可以使dis中每個(gè)元素的值大約為1.08e16,是一個(gè)較大值 for(int i = 1; i <= n; ++i)for(int j = 1; j <= n; ++j)if(edge[i][j] > 0)dis[i][j] = edge[i][j];for(int k = 1; k <= n; ++k)for(int i = 1; i <= n; ++i)for(int j = 1; j <= n; ++j)if(dis[i][j] > dis[i][k] + dis[k][j])dis[i][j] = dis[i][k] + dis[k][j]; } int main() {init();floyd();cout << fixed << setprecision(2) << dis[st][te];return 0; }

解法2:樸素Dijkstra算法+鄰接矩陣

#include<bits/stdc++.h> using namespace std; #define N 105 struct Cord {int x, y; }; double edge[N][N]; int n, m, st, te;//st:起點(diǎn) te:終點(diǎn) double dis[N];//dis[i]:st到頂點(diǎn)i的最短距離 bool vis[N]; Cord ver[N];//保存每個(gè)頂點(diǎn)的坐標(biāo) double getDis(Cord a, Cord b)//獲取點(diǎn)a到點(diǎn)b兩點(diǎn)間直線距離 {return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } void init() {int f, t;cin >> n;for(int i = 1; i <= n; ++i)cin >> ver[i].x >> ver[i].y;cin >> m;for(int i = 1; i <= m; ++i){cin >> f >> t;edge[f][t] = edge[t][f] = getDis(ver[f], ver[t]);//頂點(diǎn)f到頂點(diǎn)t的邊的權(quán)值為點(diǎn)f到點(diǎn)t的直線距離 }cin >> st >> te; } void dijkstra() {memset(dis, 0x43, sizeof(dis));//這樣可以使dis中每個(gè)元素的值大約為1.08e16,是一個(gè)較大值dis[st] = 0; for(int k = 1; k <= n; ++k){int u = 0;for(int i = 1; i <= n; ++i)if(vis[i] == false && (u == 0 || dis[i] < dis[u]))u = i;vis[u] = true;for(int v = 1; v <= n; ++v){if(edge[u][v]){double w = edge[u][v];if(vis[v] == false && dis[v] > dis[u] + w)dis[v] = dis[u] + w;}}} } int main() {init();dijkstra();cout << fixed << setprecision(2) << dis[te];return 0; }

解法3:SPFA算法+鄰接矩陣

#include<bits/stdc++.h> using namespace std; #define N 105 struct Cord {int x, y; }; double edge[N][N]; int n, m, st, te;//st:起點(diǎn) te:終點(diǎn) double dis[N];//dis[i]:st到頂點(diǎn)i的最短距離 bool vis[N]; //vis[i]:i是否在隊(duì)列內(nèi) Cord ver[N];//保存每個(gè)頂點(diǎn)的坐標(biāo) double getDis(Cord a, Cord b)//獲取點(diǎn)a到點(diǎn)b兩點(diǎn)間直線距離 {return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } void init() {int f, t;cin >> n;for(int i = 1; i <= n; ++i)cin >> ver[i].x >> ver[i].y;cin >> m;for(int i = 1; i <= m; ++i){cin >> f >> t;edge[f][t] = edge[t][f] = getDis(ver[f], ver[t]);//頂點(diǎn)f到頂點(diǎn)t的邊的權(quán)值為點(diǎn)f到點(diǎn)t的直線距離 }cin >> st >> te; } void spfa() {memset(dis, 0x43, sizeof(dis));//這樣可以使dis中每個(gè)元素的值大約為1.08e16,是一個(gè)較大值queue<int> que;dis[st] = 0; que.push(st);vis[st] = true;while(que.empty() == false){int u = que.front();que.pop();vis[u] = false;for(int v = 1; v <= n; ++v){if(edge[u][v]){double w = edge[u][v];if(dis[v] > dis[u] + w){dis[v] = dis[u] + w;if(vis[v] == false){vis[v] = true;que.push(v);} }}}} } int main() {init();spfa();cout << fixed << setprecision(2) << dis[te];return 0; }

解法4:Dijkstra堆優(yōu)化算法+鄰接表

#include<bits/stdc++.h> using namespace std; #define N 105 struct Cord {int x, y; }; struct Edge {int t;double w;Edge(){}Edge(int a, double b):t(a),w(b){} }; struct Pair {int u;//u:頂點(diǎn)double d;//距離 Pair(){}Pair(int a, double b):u(a),d(b){}bool operator < (const Pair &b) const{return b.d < d;} }; vector<Edge> edge[N]; int n, m, st, te;//st:起點(diǎn) te:終點(diǎn) double dis[N];//dis[i]:st到頂點(diǎn)i的最短距離 bool vis[N]; //vis[i]:i是否在隊(duì)列內(nèi) Cord ver[N];//保存每個(gè)頂點(diǎn)的坐標(biāo) double getDis(Cord a, Cord b)//獲取點(diǎn)a到點(diǎn)b兩點(diǎn)間直線距離 {return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } void init() {int f, t;double w;cin >> n;for(int i = 1; i <= n; ++i)cin >> ver[i].x >> ver[i].y;cin >> m;for(int i = 1; i <= m; ++i){cin >> f >> t;w = getDis(ver[f], ver[t]); edge[f].push_back(Edge(t, w));edge[t].push_back(Edge(f, w)); }cin >> st >> te; } void dijkstra() {priority_queue<Pair> pq;memset(dis, 0x43, sizeof(dis));//這樣可以使dis中每個(gè)元素的值大約為1.08e16,是一個(gè)較大值dis[st] = 0;pq.push(Pair(st, 0));while(pq.empty() == false){int u = pq.top().u;pq.pop();if(vis[u])//如果頂點(diǎn)u已經(jīng)訪問過,則跳過 continue;vis[u] = true;for(int i = 0; i < edge[u].size(); ++i) {int v = edge[u][i].t;double w = edge[u][i].w; if(vis[v] == false && dis[v] > dis[u] + w)//松弛{dis[v] = dis[u] + w;pq.push(Pair(v, dis[v]));}}} } int main() {init();dijkstra();cout << fixed << setprecision(2) << dis[te];return 0; }

總結(jié)

以上是生活随笔為你收集整理的信息学奥赛一本通 1342:【例4-1】最短路径问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。