狄克斯特拉演算法求解村莊問題
阿新 • • 發佈:2018-12-30
問題:
給定n個村莊之間的交通圖。若村莊i和j之間有路可通,則i和j用邊連線,邊上的權值Wij表示這條道路的長度。現打算在這n個村莊中選定一個村莊建一所醫院。編寫如下演算法:
(1) 求出該醫院應建在哪個村莊,才能使距離醫院最遠的村莊到醫院的路程最短。
(2) 求出該醫院應建在哪個村莊,能使其它所有村莊到醫院的路徑總和最短。
完成專案程式碼如下:
resource.h標頭檔案
//{{NO_DEPENDENCIES}} // Microsoft Visual C++ generated include file. // Used by Resource.rc // 新物件的下一組預設值 // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 101 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1001 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif
targetver.h標頭檔案
#pragma once
// 包括 SDKDDKVer.h 將定義可用的最高版本的 Windows 平臺。
// 如果要為以前的 Windows 平臺生成應用程式,請包括 WinSDKVer.h,並將
// WIN32_WINNT 巨集設定為要支援的平臺,然後再包括 SDKDDKVer.h。
#include <SDKDDKVer.h>
stdafx.h標頭檔案
// stdafx.h : 標準系統包含檔案的包含檔案, // 或是經常使用但不常更改的 // 特定於專案的包含檔案 // #pragma once #include "targetver.h" #include <stdio.h> #include <tchar.h> // TODO: 在此處引用程式需要的其他標頭檔案 #include<iostream> #include<fstream> #include<sstream> #include<string> using namespace std; const int MAX_N = 100;//定義最大儲存空間 const int INF = 65535;//定義為無窮大 //資料節點 //頂點資訊 class Vertex { public: int vername;//頂點名 int number;//頂點下標 }; //圖資訊 class MatrixGraph { public: int edges[MAX_N][MAX_N];//邊 int Tvertex, Tedges;//總頂點,總邊數 Vertex vert[MAX_N];//頂點資訊 int weight[MAX_N];//邊權重 }; class Graph { public: //構造 Graph(); //析構 ~Graph(); //讀取檔案->圖資訊 void getInfo(string ); //建立圖 void CreateGraphMatrix(); //求任意二者間最短距離 void solveMin(); //求解問題 void solveQuestion(); private: MatrixGraph graph; string vertex;//頂點 string weight;//權重 string edges[MAX_N];//邊 int Tedges;//邊數 stringstream sstr;//string型別轉換變數 int disMin[MAX_N][MAX_N];//最短距離 //獲取下標 int location(MatrixGraph , int ); //初始化鄰接矩陣 void InitMatrix(); //初始化距離陣列和路徑陣列 void InitDist(); };
stdafx.cpp檔案
// stdafx.cpp : 只包括標準包含檔案的原始檔 // solveGraphQuestion.pch 將作為預編譯頭 // stdafx.obj 將包含預編譯型別資訊 #include "stdafx.h" // TODO: 在 STDAFX.H 中 // 引用任何所需的附加標頭檔案,而不是在此檔案中引用 //構造 Graph::Graph() { Graph::InitMatrix();//初始化矩陣 Graph::InitDist();//初始化距離 } //析構 Graph::~Graph(){} //搜尋下標 int Graph::location(MatrixGraph g, int index) { for (int i = 0; i < g.Tvertex; i++) { if (index == g.vert[i].number) { return i; } } return -1; } //鄰接矩陣初始化 void Graph::InitMatrix() { { for (int i = 0; i < MAX_N; i++) { for (int j = 0; j < MAX_N; j++) { graph.edges[i][j] = INF;//初始化為無窮大 } } } } //村莊間距離初始化 void Graph::InitDist() { for (int i = 0; i < MAX_N; i++) { for (int j = 0; j < MAX_N; j++) { disMin[i][j] = INF;//初始化為無窮大 } } } //讀取檔案->圖資訊 void Graph::getInfo(string filename) { ifstream readfile; readfile.open(filename, ios::in); getline(readfile, vertex);//讀取頂點 getline(readfile, weight);//讀取權重 //讀取邊 int i = 0; while (!readfile.eof()) { if (getline(readfile, edges[i]).good())//邊值正常 { i++; } } readfile.close(); Tedges = i;//總邊數 } //建立圖 void Graph::CreateGraphMatrix() { int edge1, edge2; graph.Tvertex = vertex.length();//頂點數 graph.Tedges = Tedges;//邊數 //處理頂點 for (int i = 0; i < graph.Tvertex; i++) { //轉換 sstr.clear();//清空記憶體 sstr << vertex[i];//寫入一個頂點 sstr >> graph.vert[i].vername;//獲取一個頂點 graph.vert[i].number = i;//定義頂點編號 } //處理邊 for (int i = 0; i < graph.Tedges; i++) { //轉換 sstr.clear();//清空記憶體 sstr << weight[i];//寫入權重 sstr >> graph.weight[i];//獲取權重 sstr.clear(); sstr << edges[i][0];//獲取一條邊始點 sstr >> edge1; sstr.clear(); sstr << edges[i][1];//獲取一條邊終點 sstr >> edge2; int p1 = location(graph, edge1);//獲取始點邊下標 int p2 = location(graph, edge2);//獲取終點邊下標 graph.edges[p1][p2] = graph.edges[p2][p1] = graph.weight[i];//寫入該邊權重->無向 } } //求任意村莊間最短距離 void Graph::solveMin() { //預設最短距離 for (int i = 0; i < graph.Tvertex; i++) { for (int j = 0; j < graph.Tvertex; j++) { disMin[i][j] = graph.edges[i][j]; } } //求最短距離 for (int k = 0; k < graph.Tvertex; k++) { for (int i = 0; i < graph.Tvertex; i++) { for (int j = 0; j < graph.Tvertex; j++) { if (disMin[i][j]>disMin[i][k] + disMin[k][j]) { disMin[i][j] = disMin[i][k] + disMin[k][j];//修改最短距離 } } } } } //求解問題 void Graph::solveQuestion() { int min[MAX_N];//某村莊到其他村莊的最短距離中的最大距離 int totalMin[MAX_N] = { 0 };//某村莊到其他村莊的最短距離之和 //遍歷求村莊到其他村莊的最短距離中的最大距離 //以及到其他村莊的最短距離之和 for (int i = 0; i < graph.Tvertex; i++) { min[i] = disMin[i][0];//預設距離最大 for (int j = 0; j<graph.Tvertex; j++) { //若存在更大值,則更新 if (min[i] < disMin[i][j]) { min[i] = disMin[i][j];//修改最大值 } totalMin[i] += disMin[i][j];//距離之和 } } //求解問題 int ques_1 = min[0], loc_1 = 0;//問題一最小值以及村莊下標 int ques_2 = totalMin[0], loc_2 = 0;//問題二最小值以及村莊下標 for (int i = 0; i < graph.Tvertex; i++) { //存在更小距離 if (ques_1>min[i]) { ques_1 = min[i];//修改距離 loc_1 = i;//修改村莊下標 } //存在更小距離之和 if (ques_2 > totalMin[i]) { ques_2 = totalMin[i];//修改距離 loc_2 = i;//修改下標 } } //輸出結果 cout << "question 1->村莊標號 " << loc_1 << ", 最短距離 " << ques_1 << endl; cout << "question 2->村莊標號 " << loc_2 << ", 最短距離 " << ques_2 << endl; }
solveGraphQuestion.cpp檔案
// solveGraphQuestion.cpp : 定義控制檯應用程式的入口點。
//
//程式碼所解決問題說明見readMe.txt
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
Graph g;
g.getInfo("data.txt");//讀圖
g.CreateGraphMatrix();//建立臨接矩陣
g.solveMin();//求所有最短路徑
g.solveQuestion();//求解問題
return 0;
}
data.txt檔案資訊
012345
5873459561
01
02
03
05
12
23
25
34
35
45
執行結果: