(Dijkstra算法)設計實現一個全國大城市間的交通諮詢程序,爲旅客提供三種最優決策方案:(1)飛行時間最短(2)費用最小(3)中轉次數最少。

設計實現一個全國大城市間的交通諮詢程序,爲旅客提供三種最優決策方案:

1)飛行時間最短

(2)費用最小

(3)中轉次數最少

數據如下:

機  號                     

出 發 地

到 達 地

出發時間

到達時間

費  用 

6320

北京

上海

上海

北京

16:20

18:00  

17:25

19:05

680元

2104

北京

烏魯木齊

烏魯木齊

  北京

8:00

10:45

9:55

11:40

1150元

201

  北京

  西安

  西安

  北京

15:25

12:35

17:00

14:15

930元

2323

  西安

廣州

  廣州

  西安

7:15

10:15

9:35

11:35

1320元

173

  拉薩

  昆明

  昆明

拉薩

10:20

12:35

11:45

14:00

830元

3304

  拉薩

  武漢

  武漢

拉薩

14:15

16:25

15:45

17:55

890元

82

  烏魯木齊

    昆明

  昆明

烏魯木齊 

9:30

13:05

12:15

15:50

1480元

4723

  武漢

廣州

 廣州

 武漢

7:05

11:25

8:45

13 :05

810元

這是一道數據結構的題目,知識點爲數據結構中的圖,利用迪傑斯特拉(Dijkstra)算法求解單源路徑最短問題。

關於Dijkstra算法的思路:

1.將圖上的初始點看作一個集合S,其它點看作另一個集合

2.根據初始點,求出其它點到初始點的距離d[i] (若相鄰,則d[i]爲邊權值;若不相鄰,則d[i]爲無限大)

3.選取最小的d[i](記爲d[x]),並將此d[i]邊對應的點(記爲x)加入集合S

(實際上,加入集合的這個點的d[x]值就是它到初始點的最短距離)

4.再根據x,更新跟 x 相鄰點 y 的d[y]值:d[y] = min{ d[y], d[x] + 邊權值w[x][y] },因爲可能把距離調小,所以這個更新操作叫做鬆弛操作。

( 因爲第三步只更新並確定了x點到初始點的最短距離,集合內其它點是之前加入的,也經歷過第 4 步,所以與 x 沒有相鄰的點的 d 值是已經更新過的了,不會受到影響)

5.重複3,4兩步,直到目標點也加入了集合,此時目標點所對應的d[i]即爲最短路徑長度。

具體操作可以看這個例子,動圖很快,最好自己動手一步一步地操作一遍就大概懂了

Dijkstra算法示例

聲明:這裏的Dijkstra算法講解參考了另一位博主的文章,鏈接如下https://blog.csdn.net/Kprogram/article/details/81225176

下面開始編程思路分析:

        查詢8個城市中任意城市到其他城市的最低價,最短時間和最短路徑信息,也就是對8個不同數據元進行三種不同的操作。而這三個操作又有共同特點,查詢最短距離,最低價格,最短時間,都是求圖中一個頂點到其他所有頂點的最短距離,只是權值不一樣,核心都是單源路徑最短問題,用的算法都是Dijkstra算法。所以可以單獨寫一個迪傑斯特拉算法,根據三種不同需求,傳入邊權值,返回對應的最短路徑。這樣避免了代碼的重複。

代碼演示:

頭文件MGraph.h

#include <stdio.h>
#define maxVertices 30   //圖中頂點數目的最大值
#define maxEdges 900     //最大邊數
#define maxWeight 32767
#define impossibleVablue '#'
#define impossibleWeight -1
typedef int Type;		//頂點數據的數據類型
typedef int Weight;		//邊上權值的數據類型
typedef struct{
    int numVertices,numEdges;					//圖中實際頂點個數和邊的條數
    Type VerticesList[maxVertices];				//頂點表
    Weight Edge[maxVertices][maxVertices]; 		//鄰接矩陣
}MGraph;


int getVertexPos(MGraph& G,Type x)		//從頂點的數據值找出該頂點的頂點號,如果查找失敗,返回-1
{
    for(int i=0;i<G.numVertices;i++)
    {
        if(G.VerticesList[i]==x)
            return i;
    }
    return -1;
}


int numberOfVertices(MGraph& G)   //返回圖中當前已有的頂點個數
{
    return G.numVertices;
}

void createMGraph(MGraph& G,Type v[],int n,Type ed[][2],Weight c[],int e)  //頂點數據存放在v[],邊的頂點對分別存放於ed[e][0],ed[e][1],權值存放在c[e]
{
    G.numVertices=n;G.numEdges=e;
    int i,j,k;
    for(i=0;i<G.numVertices;i++)   //初始化
    {
        G.VerticesList[i]=v[i];
        for(j=0;j<G.numVertices;j++)
            G.Edge[i][j]=(i==j) ? 0:maxWeight;			//初始化鄰接矩陣 
    }
    for(k=0;k<G.numEdges;k++)      //建立鄰接矩陣
    {
        i=getVertexPos(G,ed[k][0]);  //使用ed[][]將頂點值轉換爲頂點號,建立圖 
        j=getVertexPos(G,ed[k][1]);
        G.Edge[i][j]=c[k];         //邊賦值
    }
}

void ShortestPath(MGraph& G,int v,Weight dist[],int path[])//dist[j]存放當前求到的從頂點v到頂點j的最短路徑長度,path[j]存放求到的最短路徑長度
{
    int n=numberOfVertices(G);
    int S[maxVertices];//最短路徑頂點集
    int i,j,k;
    Weight w,min;
    for(i=0;i<n;i++)
    {
        dist[i]=G.Edge[v][i];
        S[i]=0;
        if(i!=v&&dist[i]<maxWeight)
            path[i]=v;
        else
            path[i]=-1;
    }
    S[v]=1;  dist[v]=0;  //頂點v加入S集合
    for(i=0;i<n-1;i++)
    {
        min=maxWeight;
        int u=v;
        for(j=0;j<n;j++)
            if(!S[j]&&dist[j]<min){
                u=j;
                min=dist[j];
            }
        S[u]=1;
        for(k=0;k<n;k++){
            w=G.Edge[u][k];
            if(!S[k]&&w < maxWeight && dist[u]+w < dist[k])
            {
                dist[k]=dist[u]+w;
                path[k]=u;//頂點k未加入S,且繞過u可以縮短路徑
            }
        }

    }

}

void printShortestPath_price(MGraph& G,int v,Weight dist[],int path[])
{
    printf("從城市[%d]到其他城市的費用爲:\n",G.VerticesList[v]);
    int i,j,k,n=numberOfVertices(G);
    int d[maxVertices];
    for(i=0;i<n;i++)  //逐個頂點輸出v0-vi最短路徑
        if(i!=v){
            j=i;k=0;
            while(j!=v){
                d[k++]=j;
                j=path[j];
            }
            d[k++]=v;
            printf("到城市[%d]的最短路徑長度爲:",G.VerticesList[i]);
            while(k>0)
                printf("%d",G.VerticesList[d[--k]]);
        printf("\n費用爲:%d元\n",dist[i]);
    }
}


void printShortestPath_time(MGraph& G,int v,Weight dist[],int path[])
{
    printf("從城市[%d]到其他城市的飛行時間爲:\n",G.VerticesList[v]);
    int i,j,k,n=numberOfVertices(G);
    int d[maxVertices];
    for(i=0;i<n;i++)
    if(i!=v){
        j=i;k=0;
        while(j!=v){
            d[k++]=j;
            j=path[j];
        }
        d[k++]=v;
        printf("到城市[%d]的最短路徑長度爲:",G.VerticesList[i]);
        while(k>0)
            printf("%d",G.VerticesList[d[--k]]);
        printf("\n飛行時間爲:%d\n",dist[i]);
    }
}

void printShortestPath_num(MGraph& G,int v,Weight dist[],int path[])
{
    printf("從城市[%d]到其他城市的中轉次數爲:\n",G.VerticesList[v]);
    int i,j,k,n=numberOfVertices(G);
    int d[maxVertices];
    for(i=0;i<n;i++)
    if(i!=v){
        j=i;k=0;
        while(j!=v){
            d[k++]=j;
            j=path[j];
        }
        d[k++]=v;
        printf("到城市[%d]的最短路徑長度爲:",G.VerticesList[i]);
        while(k>0)
            printf("%d",G.VerticesList[d[--k]]);
        printf("\n中轉次數爲:%d\n",dist[i]-1);
    }
}

主函數main.cpp

#include "MGraph.h"
#include <iostream>
using namespace std;
int main()
{
    MGraph G;

    int location,operation;
    int n=8,e=16;
    int path[20];


    Type v[8]={0,1,2,3,4,5,6,7};
    Type ed[16][2]={0,1,1,0,0,2,2,0,0,3,3,0,3,4,4,3,5,6,6,5,5,7,7,5,2,6,6,2,7,4,4,7};		//存儲圖中的鏈接情況,數值爲各個地點的編號,16組是因爲8對頂點,相互有16個關係。 
    Weight a[16]={680,680,1150,1150,930,930,1320,1320,830,830,890,890,1480,1480,810,810}; //價格權值 
    Weight b[16]={65,65,115,115,95,95,140,140,85,85,90,90,165,165,100,100}; 	//時間權值 
    Weight c[16]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};			//中轉次數權值 
    Weight dist[100];

    cout <<"請輸入開始的城市(0:北京,1:上海:2:烏魯木齊,3:西安,4:廣州,5:拉薩,6:昆明,7:武漢):"<<endl;
    cin >> location;
    cout << "請輸入選擇的操作(1:查詢最低價格,2:查詢最短飛行時間,3:中轉次數最少):" << endl;
    cin >> operation;

    switch(operation){
    case 1:{
        createMGraph(G,v,n,ed,a,e);
        ShortestPath(G,location,dist,path);
        printShortestPath_price(G,location,dist,path);
        break;}
    case 2:{
        createMGraph(G,v,n,ed,b,e);
        ShortestPath(G,location,dist,path);
        printShortestPath_time(G,location,dist,path);
        break;}
    case 3:{
        createMGraph(G,v,n,ed,c,e);
        ShortestPath(G,location,dist,path);
        printShortestPath_num(G,location,dist,path);
        break;}
    default:
        break;
    }

    return 0;



}

在同一個文件夾下運行,得到結果爲:

路徑數字爲城市代碼的順序

OVER

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章