1. 程式人生 > >06-圖5. 旅遊規劃

06-圖5. 旅遊規劃

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

輸入格式說明:

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

輸出格式說明:

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

樣例輸入與輸出:

序號 輸入 輸出
1
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
2
2 1 0 1
1 0 2 3
2 3

本題是一個Dijkstra的變式應用題,思考難度個人覺得比較大。關鍵在於題目中說的,在路徑都最短時輸出花費最小的那個路徑。就對原有的Dijkstra演算法做了兩點改動。都在找到最小邊加入之後更新其他邊時發生,一是當找到新加點的最短路徑後,將路徑和花費金錢都更新。二是若找到最短路徑和原有的最短路徑相同。那麼只更新花費為小的那個即可。因為此題並沒有要求輸出最小的那個路徑,所以在這一步裡沒有必要去做父親結點陣列。但如果要求輸出路徑,就需要再開一個數組做回朔了。

#include<cstdio> 
#include<iostream>
#define INFINITY 100000
//#define LOCAL

typedef struct {
    int length,cost;
}Point;

Point G[505][505];

using namespace std;

int Dijkstra(int N,int star,int* D,int* C);

int main(){
#ifdef LOCAL
    freopen("data.in","r",stdin);
    freopen("data.out","w"
,stdout); #endif int N,M,S,D,city1,city2,Length,Cost; cin >> N >> M >> S >> D; int i,j; // 初始化 for(i = 0;i<N;i++) for(j = 0;j<N;j++) G[i][j].length = G[i][j].cost = INFINITY; // 讀入一系列點 for(i = 0;i<M;i++){ cin >> city1 >> city2 >> Length >> Cost; G[city1][city2].length = G[city2][city1].length = Length; G[city1][city2].cost = G[city2][city1].cost = Cost; } int MinDist[N],MinCost[N]; Dijkstra(N,S,MinDist,MinCost); cout << MinDist[D] << " " << MinCost[D] ; return 0; } int Dijkstra(int N,int star,int* D,int* C){ int Final[505],j,i,minD,minV; // 對起始點初始化 for(i = 0;i<N;i++){ Final[i] = 0; D[i] = G[star][i].length; C[i] = G[star][i].cost; } // 特殊點初始化 D[star] = 0; C[star] = 0; Final[star] = 1; for(j = 1;j<N;j++){ minD = INFINITY; // 查詢最小邊 for(i = 0;i<N;i++) if(!Final[i] && D[i]<minD){ minV = i; minD = D[i]; } // 僅在此處訪問邊 if(minD < INFINITY) Final[minV] = 1; else return -1; // 邊被訪問後其他點做出更新 for(i = 0;i<N;i++) if( !Final[i] ){ // 如果有最短路,更新路徑和花費 if(D[minV] + G[minV][i].length < D[i]){ D[i] = D[minV] + G[minV][i].length; C[i] = C[minV] + G[minV][i].cost; } // 如果出現相同最短路,更新為最小花費 else if(D[minV] + G[minV][i].length == D[i] && C[minV] + G[minV][i].cost < C[i]) C[i] = C[minV] + G[minV][i].cost; } } return 0; }