1. 程式人生 > >07-圖6 旅遊規劃

07-圖6 旅遊規劃

include onclick -i 圖片 str 技術分享 線圖 代碼 解決

一、題目

有了一張自駕旅遊路線圖,你會知道城市間的高速公路長度、以及該公路要收取的過路費。現在需要你寫一個程序,幫助前來咨詢的遊客找一條出發地和目的地之間的最短路徑。如果有若幹條路徑都是最短的,那麽需要輸出最便宜的一條路徑。

輸入格式:

輸入說明:輸入數據的第1行給出4個正整數N、M、S、D,其中N(2)是城市的個數,順便假設城市的編號為0~(N1);M是高速公路的條數;S是出發地的城市編號;D是目的地的城市編號。隨後的M行中,每行給出一條高速公路的信息,分別是:城市1、城市2、高速公路長度、收費額,中間用空格分開,數字均為整數且不超過500。輸入保證解的存在。

輸出格式:

在一行裏輸出路徑的長度和收費總額,數字間以空格分隔,輸出結尾不能有多余空格。

輸入樣例:

4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20

輸出樣例:

3 40
二、思路

對Dijkstra的改編(增添了fare數組)

關鍵邏輯:

1.fare的優先級低於dist。也就是一旦收錄V導致其Neighbor Node(記為W)發生改變,同時更新dist[W]與fare[W]。

2.當發現另一條最短路也能達到dist,比較fare大小,若大,則更新fare與parent(記錄路徑的數組)

三、參考源代碼

(notes: 大部分是Copy慕課上老師給出的參考代碼,

createMGraph太懶了就自己寫了。)

技術分享圖片
#include <cstdio>
#include <stdlib.h>
const int INFINITY = 65536;
const int MaxVertexNum = 501;
const int ERROR = -1;
int dist[MaxVertexNum], path[MaxVertexNum], collected[MaxVertexNum],fare[MaxVertexNum];
typedef int Vertex;
typedef int WeightType;

typedef 
struct GNode * MGraph; struct GNode { int Nv; int Ne; WeightType G[MaxVertexNum][MaxVertexNum]; WeightType F[MaxVertexNum][MaxVertexNum]; }; Vertex FindMinDist( MGraph Graph ) { /* 返回未被收錄頂點中dist最小者 */ Vertex MinV, V; int MinDist = INFINITY; for (V=0; V<Graph->Nv; V++) { if ( collected[V]==false && dist[V]<MinDist) { /* 若V未被收錄,且dist[V]更小 */ MinDist = dist[V]; /* 更新最小距離 */ MinV = V; /* 更新對應頂點 */ } } if (MinDist < INFINITY) /* 若找到最小dist */ return MinV; /* 返回對應的頂點下標 */ else return ERROR; /* 若這樣的頂點不存在,返回錯誤標記 */ } void init(MGraph Graph) { Vertex V; for( V=0; V<Graph->Nv; V++) { fare[V] = INFINITY; } } bool Dijkstra( MGraph Graph, Vertex S ) { Vertex V, W; /* 初始化:此處默認鄰接矩陣中不存在的邊用INFINITY表示 */ for ( V=0; V<Graph->Nv; V++ ) { dist[V] = Graph->G[S][V]; fare[V] = Graph->F[S][V]; if ( dist[V]<INFINITY ) path[V] = S; else path[V] = -1; collected[V] = false; } /* 先將起點收入集合 */ dist[S] = 0; collected[S] = true; while (1) { /* V = 未被收錄頂點中dist最小者 */ V = FindMinDist( Graph ); if ( V==ERROR ) /* 若這樣的V不存在 */ break; /* 算法結束 */ collected[V] = true; /* 收錄V */ for( W=0; W<Graph->Nv; W++ ) /* 對圖中的每個頂點W */ /* 若W是V的鄰接點並且未被收錄 */ if ( collected[W]==false && Graph->G[V][W]<INFINITY ) { if ( Graph->G[V][W]<0 ) /* 若有負邊 */ return false; /* 不能正確解決,返回錯誤標記 */ /* 若收錄V使得dist[W]變小 */ if ( dist[V]+Graph->G[V][W] < dist[W]) { dist[W] = dist[V]+Graph->G[V][W]; /* 更新dist[W] */ path[W] = V; /* 更新S到W的路徑 */ fare[W] = fare[V]+Graph->F[V][W]; } /*若收錄V使得fare[W]變小*/ else if(dist[V]+Graph->G[V][W] == dist[W] and fare[V] + Graph->F[V][W] < fare[W] ) { path[W] = V; /* 更新S到W的路徑 */ fare[W] = fare[V]+Graph->F[V][W]; } } } /* while結束*/ return true; /* 算法執行完畢,返回正確標記 */ } MGraph buildGraph(int Nv, int Ne) { int S, E, len, fees; MGraph Graph = (MGraph) malloc(sizeof(struct GNode)); //init Graph->Nv = Nv; Graph->Ne = Ne; for(int i=0; i<Nv; i++) { for(int j=0; j<Nv; j++) { Graph->G[i][j] = INFINITY; Graph->F[i][j] = INFINITY; } } for(int i=0; i<Ne; i++) { scanf("%d %d %d %d", &S, &E, &len, &fees); Graph->G[S][E] = len; Graph->G[E][S] = len; Graph->F[E][S] = fees; Graph->F[S][E] = fees; } return Graph; } int main() { int N, M, S, D; scanf("%d%d%d%d", &N, &M, &S, &D); MGraph Graph = buildGraph(N, M); Dijkstra(Graph, S); printf("%d %d\n", dist[D], fare[D]); }
soure_code

07-圖6 旅遊規劃