1. 程式人生 > 實用技巧 >PAT甲級1087All Roads Lead to Rome

PAT甲級1087All Roads Lead to Rome

題目連結

https://pintia.cn/problem-sets/994805342720868352/problems/994805379664297984

題解

題目要求

找到成本最低、快樂值總和最高的路徑。優先找成本最低的,然後再找快樂值最高的,然後再找平均快樂值最高的。

  • 輸入
    • N:正整數,[2,200],城市的數量
    • K:正整數,路徑的數量
    • 起始城市的名稱
    • N-1個城市的名字及其快樂值
    • K條路徑
  • 輸出
    • 成本最低的路徑的數量
    • 成本
    • 快樂值總和
    • 平均快樂值(只輸出整數部分)
    • 路徑

解題思路

這是一道dijkstra+DFS的題,和PAT甲級1018Public Bike Management很類似,所以詳細思路不再說明。

  • 用兩個map將城市的名字和索引相互對應
  • 用dijkstra演算法求出起始城市到所有城市的最短距離,並記錄每個城市的前驅城市
  • 使用DFS求出路徑(並計算、比較快樂值總和與平均值)

程式碼

// Problem: PAT Advanced 1087
// URL: https://pintia.cn/problem-sets/994805342720868352/problems/994805379664297984
// Tags: 圖 最短路 單源最短路 dijkstra BFS DFS

#include <iostream>
#include <map>
#include <vector>
#include <string>
using namespace std;

int n, k;
string startCity;

map<string, int> sti;
map<int, string> its;

const int INF = 9999999;
const int MAXN = 201;
int dis[MAXN][MAXN];
int minDis[MAXN];
bool visited[MAXN];
int happiness[MAXN];
vector<int> pre[MAXN];
vector<int> path;
vector<int> tempPath;
int ansHappinessSum = -INF, ansPathNum = 0;
double ansHappinessAve = -INF;

void dfs(int v){
    tempPath.push_back(v);

    if (v == 1){ // 到達起點
        int happinessSum = 0;
        for (auto iter = tempPath.begin(); iter != tempPath.end(); iter++)
            happinessSum += happiness[*iter];
        double happinessAve = happinessSum * 1.0 / (tempPath.size() - 1);
        if (ansHappinessSum < happinessSum){
            path = tempPath;
            ansHappinessSum = happinessSum;
            ansHappinessAve = happinessAve;
        }
        else if (ansHappinessSum == happinessSum && ansHappinessAve < happinessAve){
            path = tempPath;
            ansHappinessAve = happinessAve;
        }
        ansPathNum++;
        tempPath.pop_back();
        return ;
    }

    for (int i = 0; i < pre[v].size(); i++)
        dfs(pre[v][i]);

    tempPath.pop_back();
}

int main()
{
    fill(dis[0], dis[0] + MAXN * MAXN, INF);
    fill(minDis, minDis + MAXN, INF);

    scanf("%d %d", &n, &k);
    cin >> startCity;
    sti[startCity] = 1;
    its[1] = startCity;

    string s;
    int h;
    for (int i = 2; i <= n; i++){
        cin >> s;
        sti[s] = i;
        its[i] = s;
        scanf("%d", &h);
        happiness[i] = h;
    }
    
    string t;
    for (int i = 0; i < k; i++){
        cin >> s >> t;
        scanf("%d", &dis[sti[s]][sti[t]]);
        dis[sti[t]][sti[s]] = dis[sti[s]][sti[t]];
    }

    minDis[1] = 0;
    for (int i = 1; i <= n; i++){
        int tempMin = INF, u = -1;
        for (int j = 1; j <= n; j++){
            if (!visited[j] && tempMin > minDis[j]){
                tempMin = minDis[j];
                u = j;
            }
        }
        if (u == -1) break;
        visited[u] = true;

        for (int v = 1; v <= n; v++){
            if (!visited[v] && dis[u][v] != INF){
                if (minDis[v] > minDis[u] + dis[u][v]){
                    minDis[v] = minDis[u] + dis[u][v];
                    pre[v].clear();
                    pre[v].push_back(u);
                }
                else if (minDis[v] == minDis[u] + dis[u][v]){
                    pre[v].push_back(u);
                }
            }
        }
    }

    dfs(sti["ROM"]);

    printf("%d %d %d %d\n%s", ansPathNum, minDis[sti["ROM"]], ansHappinessSum, int(ansHappinessAve), startCity.c_str());
    for (int i = path.size() - 2; i >= 0; i--)
        printf("->%s", its[path[i]].c_str());

    return 0;
}

作者:@臭鹹魚

轉載請註明出處:https://www.cnblogs.com/chouxianyu/

歡迎討論和交流!