PAT甲级 1087 条条大路通罗马

原题链接

从我们的城市到达罗马有许多不同的旅游路线。

请你在成本最低的旅游路线之中,找到使得游客幸福感最强的路线。

输入格式
第一行包含两个整数 N 和 K,分别表示总城市数量,城市之间道路数量,还包含一个城市名字,表示初始城市。

接下来 N−1 行,每行包含一个城市名和一个整数,表示到达该城市(初始城市除外)可以获得的幸福感。

接下来 K 行,每行包含一个道路的信息,格式为 City1 City2 Cost,表示两个城市之间的道路行走的花费,道路是双向的。

城市都是由三个大写字母构成的字符串。

我们的目的地始终都是罗马 ROM。

输出格式
我们应该找到成本最低的路线。

如果这样的路线不是唯一的,那么选取使人们获得最大幸福感的路线。

如果这样的路线仍然不是唯一的,那么我们选择平均幸福感最大的路线,数据保证这种路线唯一。

平均幸福感 = 总幸福感 / 经过的城市数量(初始城市不算)

第一行输出四个整数,最小成本的路线数量,最小成本,幸福感,平均幸福感(只取整数部分)。

第二行,按照 City1->City2->...->ROM 的格式输出路线。

数据范围
2≤N≤200,
1≤K≤250,
每个城市的幸福感范围在 [0,100],
每条路线最大成本不超过 1000
输入样例:
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

我的解法:

#include <bits/stdc++.h>
using namespace std;
const int N = 210;
int n, k;
string city[N];
unordered_map <string, int> mp;
int w[N]; //  权值,此处表示每个地方的幸福度
int g[N][N];
int dist[N];
int pre[N];
bool st[N];
int cnt[N]; // 从任一点到终点rom的幸福度
int nodes[N]; // 节点数
int sum[N]; // 路线数量
void dijkstra(){
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    sum[1] = 1;
    for(int i = 0; i < n; i ++ ){
        int t = -1;
        for(int j = 1; j <= n; j ++ ){
             if(!st[j] && (t == -1 || dist[t] > dist[j])){
                 t = j;
             }
        }
        st[t] = true;
        for(int j = 1; j <= n; j ++ ){
            if(dist[t] + g[t][j] < dist[j]){
                dist[j] = dist[t] + g[t][j];
                pre[j] = t;
                cnt[j] = cnt[t] + w[j];
                nodes[j] = nodes[t] + 1;
                sum[j] = sum[t];
            }
            else if(dist[t] + g[t][j] == dist[j]){
                sum[j] += sum[t];
                if(cnt[t] + w[j] > cnt[j]){
                    pre[j] = t;
                    cnt[j] = cnt[t] + w[j];
                    nodes[j] = nodes[t] + 1;
                }
                else if(cnt[t] + w[j] == cnt[j]){
                    if(nodes[j] > nodes[t] + 1){
                        pre[j] = t;
                        nodes[j] = nodes[t] + 1;
                    }
                }
            }
        }
    }
}
int main(){
    cin >> n >> k >> city[1];
    mp[city[1]] = 1;
    for(int i = 2; i <= n; i ++ ){
        cin >> city[i] >> w[i];
        mp[city[i]] = i;
    }
    memset(g, 0x3f, sizeof g);
    while(k -- ){
        string city1, city2;
        int cost;
        cin >> city1 >> city2 >> cost;
        int a = mp[city1], b = mp[city2];
        g[a][b] = g[b][a] = min(g[a][b], cost);
    }
    dijkstra();
    int T = mp["ROM"];
    cout << sum[T] << ' ' << dist[T] << ' ' << cnt[T] << ' ' << cnt[T]/nodes[T] << endl;
    vector <int> path;
    for(int i = T; i != 1; i = pre[i] ){
        path.push_back(i);
    }
    cout << city[1];
    for(int i = path.size() - 1; i >= 0; i -- ) cout << "->" << city[path[i]];
    return 0;
}

收获:

如何让字符串和数字互相对应,使用映射的思想,定义一个字符串数组和一个哈希表来实现

猜你喜欢

转载自blog.csdn.net/weixin_45660485/article/details/124995277