【PAT甲级】1087 All Roads Lead to Rome

简介: 【PAT甲级】1087 All Roads Lead to Rome

1087 All Roads Lead to Rome

Indeed there are many different tourist routes from our city to Rome. You are supposed to find your clients the route with the least cost while gaining the most happiness.

Input Specification:

Each input file contains one test case. For each case, the first line contains 2 positive integers N (2≤N≤200), the number of cities, and K, the total number of routes between pairs of cities; followed by the name of the starting city. The next N−1 lines each gives the name of a city and an integer that represents the happiness one can gain from that city, except the starting city. Then K lines follow, each describes a route between two cities in the format City1 City2 Cost. Here the name of a city is a string of 3 capital English letters, and the destination is always ROM which represents Rome.


Output Specification:

For each test case, we are supposed to find the route with the least cost. If such a route is not unique, the one with the maximum happiness will be recommanded. If such a route is still not unique, then we output the one with the maximum average happiness – it is guaranteed by the judge that such a solution exists and is unique.


Hence in the first line of output, you must print 4 numbers: the number of different routes with the least cost, the cost, the happiness, and the average happiness (take the integer part only) of the recommanded route. Then in the next line, you are supposed to print the route in the format City1->City2->...->ROM.


Sample Input:

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


Sample Output:

3 3 195 97
HZH->PRS->ROM


题意

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


请你在成本最低的旅游路线之中,找到使得游客获得最大幸福感的路线。如果该路线不唯一,则找到最大平均幸福感的路线,其中平均幸福感是不包括起点的。


第一行输入分别为城市数量 N NN ,路线数量 K KK ,以及起点。


接下来的 N − 1 N-1N−1 行输入每个城市的幸福感值。


接下来的 K KK 行则输入每条路的信息。


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


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


思路

这道题同样可以利用迪杰斯特拉算法去找最优解,具体思路如下:


1.先对所有城市进行映射,因为给定的城市名字为字符串类型,需要映射成整数,可以用一个哈希表 mp 存储每个城市映射后的下标。

2.输入每条路的信息,注意这里需要用到上面映射后的下标进行存储,之后的迪杰斯特拉同理。

3.在进行迪杰斯特拉算法的过程中,不断更新答案,找到最优路线。首先要去判断当前路径花费是否最小,如果存在另一条花费相等的路径则要进一步判断该路径获得的幸福感是否最大,如果还是出现相等的路径则再进一步判断该路径的结点数量是否最小,然后进行对应的更新操作。

4.输出最终结果,注意需要先将 pre 中的路线全部存到一个容器中再逆向输出。


代码

#include<bits/stdc++.h>
using namespace std;
const int N = 210;
int n, k;
//最小花费、最小花费路径数量、幸福感值、最小点数、最短路径的前一个点
int dist[N], cnt[N], hp[N], sum[N], pre[N];
int d[N][N], w[N];
bool st[N];
string city[N];
unordered_map<string, int> mp;
//迪杰斯特拉算法
void dijkstra()
{
    //初始化
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0, cnt[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[j] > dist[t] + d[t][j]) //如果最小花费可以更新
            {
                dist[j] = dist[t] + d[t][j];
                cnt[j] = cnt[t];
                hp[j] = hp[t] + w[j];
                sum[j] = sum[t] + 1;
                pre[j] = t;
            }
            else if (dist[j] == dist[t] + d[t][j])   //如果最小花费相等
            {
                cnt[j] += cnt[t];
                if (hp[j] < hp[t] + w[j])    //如果幸福感可以更新
                {
                    hp[j] = hp[t] + w[j];
                    sum[j] = sum[t] + 1;
                    pre[j] = t;
                }
                else if (hp[j] == hp[t] + w[j])  //如果幸福感也相等
                {
                    if (sum[j] > sum[t] + 1) //如果存在点数更小的路径
                    {
                        sum[j] = sum[t] + 1;
                        pre[j] = t;
                    }
                }
            }
    }
}
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(d, 0x3f, sizeof d);
    for (int i = 0; i < k; i++)
    {
        string a, b;
        int x, y, c;
        cin >> a >> b >> c;
        x = mp[a], y = mp[b];
        d[x][y] = d[y][x] = min(d[x][y], c);
    }
    dijkstra(); //寻找满足要求的路径
    //输出结果
    int T = mp["ROM"];
    cout << cnt[T] << " " << dist[T] << " " << hp[T] << " " << hp[T] / sum[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]];
    cout << endl;
    return 0;
}


目录
相关文章
|
人工智能 BI C语言
1346:【例4-7】亲戚(relation)
1346:【例4-7】亲戚(relation)
116 0
|
存储
【PAT甲级】1142 Maximal Clique
【PAT甲级】1142 Maximal Clique
62 0
|
C++
【PAT甲级 - C++题解】1096 Consecutive Factors
【PAT甲级 - C++题解】1096 Consecutive Factors
83 0
|
存储 供应链 C++
【PAT甲级 - C++题解】1106 Lowest Price in Supply Chain
【PAT甲级 - C++题解】1106 Lowest Price in Supply Chain
81 0
|
存储 供应链 C++
【PAT甲级 - C++题解】1079 Total Sales of Supply Chain
【PAT甲级 - C++题解】1079 Total Sales of Supply Chain
94 0
|
机器学习/深度学习
The Preliminary Contest for ICPC China Nanchang National Invitational J题 Distance on the tree
The Preliminary Contest for ICPC China Nanchang National Invitational J题 Distance on the tree
96 0
HDU-1057,A New Growth Industry(理解题意)
HDU-1057,A New Growth Industry(理解题意)
|
移动开发 前端开发
ICPC Latin American Regional 2017-Imperial roads(LCA)
题目大意: 给出n个点,m条边的一个图,q个询问, 每次询问给出两个点u,v,问包含u-v这条边的最小生成树是多少 这道题比较板 首先求一下这个图的最小生成树对于这n个点,最小生成树一定是n-1条边,如果说再加上一条边,一定会构成一个环。 我们把生成的这个最小生成树看作是一个以1为根节点的最小生成树。 所以说在下面的q个询问中,如果说这条边用到了最小生成树中(这条边是最小生成树上的边),那么直接输出当前最小生成树的代价就好;如果说当前这条边没有出现在最小生成树当中,那么最小生成树的权值val加上这条边之后就构成了一个环,求出这两个点所在的环内的最大边权,并将这个边权减去,就是最终结果
120 0
ICPC Latin American Regional 2017-Imperial roads(LCA)
|
Java
HDU - 2018杭电ACM集训队单人排位赛 - 3 - Problem F. Four-tuples
HDU - 2018杭电ACM集训队单人排位赛 - 3 - Problem F. Four-tuples
144 0
|
人工智能 Java
HDU - 2018杭电ACM集训队单人排位赛 - 4 - Problem J. number sequence
HDU - 2018杭电ACM集训队单人排位赛 - 4 - Problem J. number sequence
140 0