(learning English and algorithms) PAT a -- All Roads Lead to Rome


My personal station: acking-you.github.io

subject


OJ platform

Topic translation

First look at this topic to know: all roads lead to Rome

Word accumulation

Indeed  In fact, indeed
routes Route
recommended Highly respected
# example sentence
Indeed there are many different tourist routes from our city to Rome.
# translate
 In fact, there are many different routes from our city to Rome.

Title Description

original text
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.

translate
In fact, there are many different routes from our city to Rome. You should find a route for your guests to spend the least and get the most happiness.

Enter description

original text
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.

translate
For each test case, the first line contains two positive integers:
N. Represents the number of cities. K. Represents the total number of roads between any two cities.
Starting city represents the city where the start is located. Next, N-1 lines, each line gives the name of the city and the happiness value you can get to the city (the first city has no happiness value).
Next, K lines are used to describe a road between two cities in the format of "city1 city2 cost", indicating the names of the two cities and the cost required for the road between them. The city names here are expressed in English words of what length, and ROM stands for Rome.

Output description

original text
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 recommended route. Then in the next line, you are supposed to print the route in the format "City1->City2->...->ROM".
translate
In the first line, you must print four numbers: 1. The number of different routes with the minimum cost, 2. The corresponding minimum cost, 3. The corresponding maximum happiness, and 4. The average happiness.
The second line prints the travel route.

Problem solving analysis

This topic is the same as the previous PAT topic: Emergency As like as two peas. Both calculate the number of edge weights and the maximum value of the simultaneous point weight to ensure the minimum edge weight. The part that needs special processing is that it does not directly enter the number, but describes the city in the form of string. Therefore, before we write Dijkstra algorithm, we first map the string and number, then the normal Dijkstra algorithm, and finally print the path through path.

Detailed explanation of problem solving code

Parameters required by the topic

//Enter the required data
int N,K;
string start;
unordered_map<string,int>check1;
const char* check2[MaxN];
int points[MaxN];

//Data needed to update answers
int nums[MaxN];//Record the shortest path to a node
int w[MaxN];//Record the maximum value of the midpoint weight of the shortest path

//Parameters required by Dij algorithm
int path[MaxN];
int dist[MaxN];
bitset<MaxN> visit;

Input module

void Input(){
    ios::sync_with_stdio(false);
    memset(head,0xff,sizeof(head));
    memset(dist,0x3f,sizeof(dist));
    cin>>N>>K>>start;
    check2[0] = start.c_str();
    for(int i=1;i<N;i++){
        string* x = new string; //The heap memory must be used, or the memory will be destroyed automatically once the range ends, and there is no data in the memory pointed to by the check2 pointer
        int point;
        cin>>(*x)>>point;
        check2[i] = x->c_str();
        points[i] = point;
        check1[(*x)] = i;
    }
    for (int i = 0; i < K; ++i){
        string x,y;int len;cin>>x>>y>>len;
        int a = check1[x],b = check1[y];
        add(a,b,len);
        add(b,a,len);
    }
}

Chain forward star construction map

//Data and operations required for drawing construction
int tot = 0;
int head[MaxN];
struct{
    int to;
    int len;
    int next;
}edge[MaxN*MaxN];
void add(int a,int b,int len){
    edge[tot].to =  b;
    edge[tot].len = len;
    edge[tot].next = head[a];
    head[a] = tot++;
}

Operation of Dij algorithm

//Dij operation
int findMin() {
    int minV = 0;
    int cmp = INF;
    for (int i = 1; i < N; i++) {
        if (!visit[i] && dist[i] < cmp) {
            cmp = dist[i];
            minV = i;
        }
    }
    visit[minV] = 1;
    return minV;
}
void Dij() {
    for (int i = 0; i < N; i++) {
        int node = findMin();
        if (node == 0)
            break;
        for (int i = head[node]; i != -1; i = edge[i].next) {
            if (!visit[edge[i].to]) {
                if (dist[edge[i].to] > edge[i].len + dist[node]) {
                    dist[edge[i].to] = edge[i].len + dist[node];
                    path[edge[i].to] = node;
                    nums[edge[i].to] = nums[node];
                    w[edge[i].to] = w[node] + points[edge[i].to];
                } else if (dist[edge[i].to] == edge[i].len + dist[node]) {
                    nums[edge[i].to] += nums[node];
                    if (w[edge[i].to] < w[node] + points[edge[i].to]) {
                        w[edge[i].to] = w[node] + points[edge[i].to];
                        path[edge[i].to] = node;
                    }
                }
            }
        }
    }
}

print operation

// Print operation, using stack to realize LIFO
void print() {
    vector<int>St;
    string end = "ROM";
    int ed = check1[end];
    int cnt = 1;
    int next = path[ed];
    while (next) {
        St.push_back(next);
        cnt++;
        next = path[next];
    }

    int happiness = w[ed];
    int average = happiness / cnt;
    cout << nums[ed] << ' ' << dist[ed] << ' ' << happiness << ' ' << average << '\n';
    cout << start;

    while (!St.empty()) {
        cout << "->" << check2[St.back()];
        St.pop_back();
    }
    cout << "->" << end;
}

Integrate the code to get the answer

Fairly efficient

My answer:

#include<bits/stdc++.h>
using namespace std;
#define MaxN 202
#define INF 0x3f3f3f3f
//Enter the required data
int N, K;
string start;
unordered_map<string, int>check1;
const char* check2[MaxN];
int points[MaxN];

//Data needed to update answers
int nums[MaxN];//Record the shortest path to a node
int w[MaxN];//Record the maximum value of the midpoint weight of the shortest path

//Parameters required by Dij algorithm
int path[MaxN];
int dist[MaxN];
bitset<MaxN> visit;

//Data required for mapping
int tot = 0;
int head[MaxN];
struct {
    int to;
    int len;
    int next;
} edge[MaxN * MaxN];
void add(int a, int b, int len) {
    edge[tot].to =  b;
    edge[tot].len = len;
    edge[tot].next = head[a];
    head[a] = tot++;
}
void Input() {
    ios::sync_with_stdio(false);
    memset(head, 0xff, sizeof(head));
    memset(dist, 0x3f, sizeof(dist));
    cin >> N >> K >> start;
    check2[0] = start.c_str();
    for (int i = 1; i < N; i++) {
        string* x = new string; //The heap memory must be used, or the memory will be destroyed automatically once the range ends, and there is no data in the memory pointed to by the check2 pointer
        int point;
        cin >> (*x) >> point;
        check2[i] = x->c_str();
        points[i] = point;
        check1[(*x)] = i;
    }
    for (int i = 0; i < K; ++i) {
        string x, y; int len; cin >> x >> y >> len;
        int a = check1[x], b = check1[y];
        add(a, b, len);
        add(b, a, len);
    }
}

//Dij operation
int findMin() {
    int minV = 0;
    int cmp = INF;
    for (int i = 1; i < N; i++) {
        if (!visit[i] && dist[i] < cmp) {
            cmp = dist[i];
            minV = i;
        }
    }
    visit[minV] = 1;
    return minV;
}
void Dij() {
    for (int i = 0; i < N; i++) {
        int node = findMin();
        if (node == 0)
            break;
        for (int i = head[node]; i != -1; i = edge[i].next) {
            if (!visit[edge[i].to]) {
                if (dist[edge[i].to] > edge[i].len + dist[node]) {
                    dist[edge[i].to] = edge[i].len + dist[node];
                    path[edge[i].to] = node;
                    nums[edge[i].to] = nums[node];
                    w[edge[i].to] = w[node] + points[edge[i].to];
                } else if (dist[edge[i].to] == edge[i].len + dist[node]) {
                    nums[edge[i].to] += nums[node];
                    if (w[edge[i].to] < w[node] + points[edge[i].to]) {
                        w[edge[i].to] = w[node] + points[edge[i].to];
                        path[edge[i].to] = node;
                    }
                }
            }
        }
    }
}


// Print operation, using stack to realize LIFO
void print() {
    vector<int>St;
    string end = "ROM";
    int ed = check1[end];
    int cnt = 1;
    int next = path[ed];
    while (next) {
        St.push_back(next);
        cnt++;
        next = path[next];
    }

    int happiness = w[ed];
    int average = happiness / cnt;
    cout << nums[ed] << ' ' << dist[ed] << ' ' << happiness << ' ' << average << '\n';
    cout << start;

    while (!St.empty()) {
        cout << "->" << check2[St.back()];
        St.pop_back();
    }
    cout << "->" << end;
}

int main() {
    Input();
    //First Dij processing
    dist[0] = 0;
    nums[0] = 1;
    for (int i = head[0]; i != -1; i = edge[i].next) {
        dist[edge[i].to] = edge[i].len;
        w[edge[i].to] = points[edge[i].to];
        nums[edge[i].to] = nums[0];
    }
    Dij();
    print();
    return 0;
}

Tags: Algorithm

Posted on Sat, 20 Nov 2021 01:30:28 -0500 by fr8