PAT(Advanced)1087 All Roads Lead to Rome Dijkstra最短路 C++實現

PAT(Advanced)甲級1087 All Roads Lead to Rome

相關內容

PAT(Advanced)1003 Emergency (Dijkstra最短路) (鄰接矩陣)C++實現
DijkstraSSSP(單源最短路徑求解)(迪克斯特拉算法堆優化)(Java實現)(鄰接矩陣)(優先級隊列)(堆優化)
Dijkstra最短路(迪克斯特拉算法)(C++實現)(鄰接矩陣)

題目鏈接

1087 All Roads Lead to Rome

題目大意

給定出發城市,存在的路線及路線長度,目的地爲羅馬,求解到達羅馬的最短路徑,除了出發城市外,每個城市有對應的幸福值,在求得最短路徑的情況下,若最短路徑不唯一則求解累積幸福值最高的路線若幸福值最高的最短路徑仍然不唯一,則求解平均幸福值最高的路線,平均幸福值爲路線總幸福值與除了出發城市外的城市數量的比值,輸出爲最小代價路徑數量最短路徑代價最短路徑中的最大幸福值具有最大幸福值的最短路徑最高平均幸福值以及具有最大幸福值和最高平均幸福值的最短路徑從出發城市到目的地羅馬的路線序列

算法思路

求解單源最短路,採用Dijkstra最短路徑算法
設置優先級隊列優先級,其中d距離優先級最高,幸福值次之,平均幸福值最小,距離越小優先級越高,距離相同情況下,幸福值越大優先級越高,距離和幸福值相同情況下,平均幸福值越高優先級越高,即路徑經過城市數越少優先級越高


struct Node{
    int num;
    int dist;
    int happiness;
    int passByCity;
    bool operator < (const Node& x) const{
        // return dist == x.dist ? happiness < x.happiness : dist > x.dist;
        return dist == x.dist ? (happiness == x.happiness ? passByCity > x.passByCity : happiness < x.happiness ) : dist > x.dist;
    }
};

更新dist數組及相應值

if (dist[i] >= dist[top] + matrix[top][i]) {
                if (dist[i] == dist[top] + matrix[top][i]) {
                	// 若dist數組對應值相等
                	// 更新路線數量
                	// 由於長度相等,則在頂點i原來的路線數量基礎上增加top爲前驅的路線數量
                    routes[i] += routes[top];
                    // 考慮路線幸福值總數和平均幸福值情況...
                    if (happinessValue[i] < happinessValue[top] + happiness[i]) {
                        happinessValue[i] = happinessValue[top] + happiness[i];
                        dijkstraSSSP[i] = top;
                        passByCityNumber[i] = passByCityNumber[top] + 1;
                        pq.push((Node) {i, dist[i], happinessValue[i], passByCityNumber[i]});
                    } else if (happinessValue[i] == happinessValue[top] + happiness[i]) {
                        if (passByCityNumber[i] > passByCityNumber[top] + 1) {
                            dijkstraSSSP[i] = top;
                            passByCityNumber[i] = passByCityNumber[top] + 1;
                            pq.push((Node) {i, dist[i], happinessValue[i], passByCityNumber[i]});
                        }
                    }
                } else {
                	// 若存在更短dist數組,則更新路線值,城市幸福值和路徑城市數量
                    routes[i] = routes[top];//更新路線數量

                    dist[i] = dist[top] + matrix[top][i];//更新dist數組對應值
                    happinessValue[i] = happinessValue[top] + happiness[i];//更新幸福值
                    dijkstraSSSP[i] = top;//更新最短路徑
                    passByCityNumber[i] = passByCityNumber[top] + 1;//更新路徑城市數量
                    pq.push((Node) {i, dist[i], happinessValue[i], passByCityNumber[i]});//將新的頂點及相關信息入堆
                }
            }

考慮路線幸福值總數和平均幸福值情況

if (happinessValue[i] < happinessValue[top] + happiness[i]) {
	// 若存在更高幸福值的最短路徑
    happinessValue[i] = happinessValue[top] + happiness[i];// 更新最短路徑
    dijkstraSSSP[i] = top;// 更新最短路徑回溯數組
    passByCityNumber[i] = passByCityNumber[top] + 1;// 更新最短路徑路徑城市數量
    pq.push((Node) {i, dist[i], happinessValue[i], passByCityNumber[i]});// 將新頂點及相關信息入堆
} else if (happinessValue[i] == happinessValue[top] + happiness[i]) {
	// 若幸福值相等
	// 考慮城市最大平均幸福值情況...
    if (passByCityNumber[i] > passByCityNumber[top] + 1) {
        dijkstraSSSP[i] = top;
        passByCityNumber[i] = passByCityNumber[top] + 1;
        pq.push((Node) {i, dist[i], happinessValue[i], passByCityNumber[i]});
    }
}

考慮城市最大平均幸福值情況

if (passByCityNumber[i] > passByCityNumber[top] + 1) {
	// 若存在更大的城市平均幸福值
	dijkstraSSSP[i] = top;// 更新最短路徑回溯數組
    passByCityNumber[i] = passByCityNumber[top] + 1;// 更新最短路徑路徑城市數量
    pq.push((Node) {i, dist[i], happinessValue[i], passByCityNumber[i]});// 將新頂點及相關信息入堆
}

首先考慮最短路徑的情況,在存在多條最短路徑的情況下,選取幸福值最高的路線,在存在多條幸福值最高且相同的最短路徑的情況下,選取最高城市平均值的最短路徑

AC代碼

/*
author : eclipse
email  : [email protected]
time   : Wed Jun 24 23:40:49 2020
*/
#include <bits/stdc++.h>
using namespace std;

const int INF = 0x10000000;
const int MAX_SIZE = 256;

int vextexNumber;
int routeNumber = 0;

vector<int> routes;
vector<int> happiness;
vector<int> happinessValue;
vector<int> dijkstraSSSP;
vector<int> dist;
vector<vector<int> > matrix;
vector<int> passByCityNumber;

map<string, int> cityOrder;
map<int, string> orderCity;

struct Node{
    int num;
    int dist;
    int happiness;
    int passByCity;
    bool operator < (const Node& x) const{
        return dist == x.dist ? (happiness == x.happiness ? passByCity > x.passByCity : happiness < x.happiness ) : dist > x.dist;
    }
};

void dijkstra() {
    vector<bool> tag;
    tag.resize(vextexNumber);
    for (int i = 0; i < vextexNumber; i++) {
        dist[i] = INF;
        dijkstraSSSP[i] = 0;
        tag[i] = false;
    }
    priority_queue<Node> pq;
    pq.push((Node) {0, 0, 0, 0});
    dist[0] = 0;
    dijkstraSSSP[0] = 0;
    while (!pq.empty()) {
        int top = pq.top().num;
        pq.pop();
        if (tag[top]) {
            continue;
        }
        tag[top] = true;
        for (int i = 0; i < vextexNumber; i++) {
            if (dist[i] >= dist[top] + matrix[top][i]) {
                if (dist[i] == dist[top] + matrix[top][i]) {
                    routes[i] += routes[top];
                    if (happinessValue[i] < happinessValue[top] + happiness[i]) {
                        happinessValue[i] = happinessValue[top] + happiness[i];
                        dijkstraSSSP[i] = top;
                        passByCityNumber[i] = passByCityNumber[top] + 1;
                        pq.push((Node) {i, dist[i], happinessValue[i], passByCityNumber[i]});
                    } else if (happinessValue[i] == happinessValue[top] + happiness[i]) {
                        if (passByCityNumber[i] > passByCityNumber[top] + 1) {
                            dijkstraSSSP[i] = top;
                            passByCityNumber[i] = passByCityNumber[top] + 1;
                            pq.push((Node) {i, dist[i], happinessValue[i], passByCityNumber[i]});
                        }
                    }
                } else {
                    routes[i] = routes[top];

                    dist[i] = dist[top] + matrix[top][i];
                    happinessValue[i] = happinessValue[top] + happiness[i];
                    dijkstraSSSP[i] = top;
                    passByCityNumber[i] = passByCityNumber[top] + 1;
                    pq.push((Node) {i, dist[i], happinessValue[i], passByCityNumber[i]});
                }
            }
        }
    }
}

void print(int destination, map<int, string> orderCity) {
    stack<int> s;
    int current = destination;
    while (current) {
        s.push(current);
        current = dijkstraSSSP[current];
    }

    printf("%d %d %d %d\n", routes[destination], dist[destination], happinessValue[destination], happinessValue[destination] / passByCityNumber[destination]);

    cout << orderCity[0];
    while (!s.empty()) {
        cout << "->" << orderCity[s.top()];
        s.pop();
    }
}

int main(int argc, char const *argv[]) {
    int N, M;


    scanf("%d%d", &N, &M);
    vextexNumber = N;
    string start;
    routes.resize(vextexNumber);
    happinessValue.resize(vextexNumber);
    dijkstraSSSP.resize(vextexNumber);
    dist.resize(vextexNumber);
    passByCityNumber.resize(vextexNumber);
    happiness.resize(vextexNumber);

    cin >> start;
    orderCity[0] = start;
    cityOrder[start] = 0;

    happiness[0] = 0;



    for (int i = 1; i < vextexNumber; i++) {
        string city;
        int value;
        cin >> city >> value;
        happiness[i] = value;
        orderCity[i] = city;
        cityOrder[city] = i;
    }


    matrix.resize(vextexNumber);

    for (int i = 0; i < vextexNumber; i++) {
        happinessValue[i] = 0;
        passByCityNumber[i] = 0;
        routes[i] = 0;
        matrix[i].resize(vextexNumber);
        routes[i] = 1;
        for (int j = 0; j < vextexNumber; j++) {
            matrix[i][j] = INF;
        }
    }

    for (int i = 0; i < M; i++) {
        string u, v;
        int weight;
        cin >> u >> v >> weight;
        matrix[cityOrder[u]][cityOrder[v]] = weight;
        matrix[cityOrder[v]][cityOrder[u]] = weight;
    }

    dijkstra();

    print(cityOrder["ROM"], orderCity);

    return 0;
}


樣例輸入

6 7 HZH
ROM 100
PKN 40
GDN 55
PRS 95
BLN 80
ROM GDN 1
BLN ROM 1
HZH PKN 1
PRS ROM 2
BLN HZH 2
PKN GDN 1
HZH PRS 1

樣例輸出

3 3 195 97
HZH->PRS->ROM

鳴謝

PAT

最後

  • 本題考慮的情況有些多,需要注意的是要考慮路線數量、經過城市數和幸福值在更新時需要繼承其直接前驅頂點的狀態,若忽略則可能無法通過某些測試點
  • 本題空間消耗比較大,若在類中寫可能會導致段錯誤,上述代碼沒有采用遞歸的方式,則段錯誤爲數組越界的錯誤,故在數組較大的情況下儘量使用全局變量,使用內存堆區
  • 由於博主水平有限,不免有疏漏之處,歡迎讀者隨時批評指正,以免造成不必要的誤解!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章