06-圖5. 旅遊規劃
阿新 • • 發佈:2019-01-04
有了一張自駕旅遊路線圖,你會知道城市間的高速公路長度、以及該公路要收取的過路費。現在需要你寫一個程式,幫助前來諮詢的遊客找一條出發地和目的地之間的最短路徑。如果有若干條路徑都是最短的,那麼需要輸出最便宜的一條路徑。
輸入格式說明:
輸入說明:輸入資料的第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;
}