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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Dijkstra(迪杰斯特拉)算法简介

發布時間:2023/11/27 生活经验 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Dijkstra(迪杰斯特拉)算法简介 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  • 適用情形
  • 思想
  • 核心代碼
  • 設計實現更多功能
  • 舉例說明

適用情形

適用于權值為非負的圖的單源最短路徑

思想

在已知起點與終點的情況下。須有三個一維數組S,U,dis,S用于記錄已經查找過的點,U則記錄未查找到的點,dis用于記錄從起點到各個點間的距離。開始時,S中僅有起點,U中則是其它所有點,dis[起點]初始化為0,dis中其它元素則為起點到各點的距離,如果沒有路徑則可以記錄為INF(無窮大)或者-1。然后尋找與起點最近的點,將它加入數組S中,再更新dis的最短路徑。然后再找與起點最近的點,將它加入數組S中,再更新dis的最短路徑。知道全部更新完成。

核心代碼

//假設已知起點為u,點間的距離已存到二維數組map中,點間沒有路徑則存INF
int INF = 1e7;
int map[100][100];
int dis[100];
int u = 0;
int N = 100;           //N表示城市的數量
int flag[100];         //以數組flag記錄點是否在數組S中void Dijkstra()
{//第一步:初始化兩個數組for(int i = 0; i < N; i++){dis[i] = map[u][i];flag[i] = 0;}flag[u] = 1;dis[u] = 0;//以循環來表示重復接下來的步驟,確保找到每個點for(int i = 0; i < N; i++){//第二步:找到距離起點的最近點int temp = INF, t = u;for(int j = 0; j < N; j++){if(!flag[j] && dis[j] < INF){t = j;temp = dis[j];}}if(t == u)return;      //全部點已被找完則退出elseflag[t] = 1; //將找到的點加入S//第三步:更新dis數組for(int j = 0; j < N; j++){if(flag[j] == 0 && map[t][j]<INF && dis[j]>(dis[t]+map[t][j])){dis[j]=dis[t]+map[t][j];}}}
}

我將DIjkstra算法分為了三個步驟,即:
第一步:初始化兩個數組
第二步:找到距離起點的最近點
第三步:更新dis數組

其中第二和第三步需用循環滿足所有的點都被搜一遍。

設計實現更多功能

1.記錄路徑
加入一個記錄中轉點的數組即可
2.計算最短路徑的條數
加入一個記錄到每個點的路徑的數量的數組即可
3.出現路徑長度相同的情況,根據每個點的權選擇特定路徑
加入一個記錄到該點的權量的數組即可

總的來說,需要實現什么功能就加上一個記錄數據變化的數組即可。具體會在下面舉例說明

舉例說明

題目

分析:在這道題目中我們發現,不僅需要尋找最短路徑的長度,還需要找到最短路徑的條數,已經救援隊數量最多的那條最短路徑,故我們需加入上一部分說的三個數組。具體代碼如下:

#include<iostream>
#define K 501using namespace std;int INF = 1e7;int N, M , S , D;
int teamnumber[K];   //記錄每個城市的救援隊數量
int map[K][K];       //記錄城市間的路徑距離
int father[K];       //記錄中轉點
int dis[K];          //記錄起點到個點間的距離
int flag[K];         //記錄每個點是否已經搜索
int number[K];       //記錄起點到各點時路徑的數量
int ts[K];           //記錄救援隊的數量void Dijkstra()
{//各數組的初始化fill(dis, dis+N, INF);fill(flag,flag+N, 0);fill(number, number+N, 0);fill(ts, ts+N, 0);for(int i = 0; i < N; i++){dis[i] = map[S][i];father[i] = i;}//我們保持flag[i] == 0,在第一次搜索中會首先檢索到它,你也可以思考一下讓它為0有什么好處dis[S] = 0;     number[S] = 1;ts[S] = teamnumber[S];//開始搜索每個點for(int i = 0; i < N; i++){int Min = INF, t = -1;for(int j = 0; j < N; j++){if(flag[j] == 0 && dis[j] < Min){Min = dis[j];t = j;}}if(t == -1)return;elseflag[t] = 1;     for(int j = 0; j < N; j++)   //注意兩條路距離相同但權值不同的情況,故分兩種情況討論{if(flag[j] == 0 && (dis[t] + map[t][j]) < dis[j] && map[t][j] < INF){dis[j] = dis[t] + map[t][j];father[j] = t;ts[j] = ts[t] + teamnumber[j];number[j] = number[t];}else if(flag[j] == 0 && (dis[t] + map[t][j]) == dis[j] && map[t][j] < INF){if((ts[t] + teamnumber [j]) > ts[j]){ts[j] = ts[t] + teamnumber[j];father[j] = t;}number[j] += number[t];}}}
}//打印路徑函數
void PP(int s, int d)
{while(father[d] != d){PP(s,father[d]);cout << father[d] << " ";return;}return;
}int main()
{cin >> N >> M >> S >> D;for(int i = 0; i < N; i++)cin >> teamnumber[i];for(int i = 0; i < N; i++){for(int j = 0; j < N; j++){map[i][j] = INF;}}int n, m ,d;for(int i = 0; i < M; i++){cin >> n >> m >> d;map[n][m] = d;map[m][n] = d;}Dijkstra();cout << number[D] << " " << ts[D] << endl;PP(S,D);cout << D;return 0;
}

需要注意的地方在代碼上都有注釋,如有問題可以在評論區提問。

總結

以上是生活随笔為你收集整理的Dijkstra(迪杰斯特拉)算法简介的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。