PAT甲级真题1001 - 1005题详细题解(C++)(个人题解)

本文为PAT甲级真题中的1001 - 1005题的详细题解,本文的解法仅个人的思路和解法,有什么更优解欢迎讨论(AI一键生成答案的年代还能坚持写题解吗?)

题目链接:真题练习

题目1001: A+B Format

题目大意:

给你两个整数a,b,范围是[-1e6, 1e6]

现在算出a + b,但是答案得从最低位开始,每三位加一个逗号

比如输入-1000000 9

输出-999,991

解题思路:

其实这个题目就很简单了,首先注意题目范围,1e6,所以加起来也就2e6,最多两个逗号

我们可以把和sum = a + b转换成字符串

实现的时候可以直接用insert方法来实现,具体实现细节可以看代码,注意负号就行了,可以先输出负号,然后把sum变成正数处理。

代码(C++):

cpp 复制代码
#include <bits/stdc++.h>

using i64 = long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int a, b;
    std::cin >> a >> b;

    int sum = a + b;
    if (sum < 0) {
        std::cout << "-";
        sum = -sum;
    }
    std::string s = std::to_string(sum);

    int sz = s.size();
    if (sz > 3) {
        s.insert(sz - 3, ",");
    }
    if (sz > 6) {
        s.insert(sz - 6, ",");
    }

    std::cout << s;
}

题目1002: A+B for Polynomials

题目大意:

现在有两个一元多项式A和B, 现在给出多项式的指数和系数

现在求出两个多项式相加的结果

解题思路:

这题我的做法是,由于指数的大小最多是1000,指数的范围是[0, 1000],所以我们可以建立一个长度为1001的数组用来记录每一个指数的系数

std::vector<double> p(1001)

然后输入两次即可,每次输入的时候,把对应位置的系数相加

p[n] += a;

然后题目中说需要输出个数,那我们可以用一个答案数组std::vector<std::pair<int, double>> ans、

注意,系数可能是负数(这个题目中好像没有详细说明),所以我们需要把数组p中绝对值大于0的元素放在答案数组里面。

具体实现细节可以参考代码

代码(C++):

cpp 复制代码
#include <bits/stdc++.h>

using i64 = long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    std::vector<double> p(1001);
    for (int t = 0; t < 2; t++) {
        int k;
        std::cin >> k;
        for (int i = 0; i < k; i++) {
            int n;
            double a;
            std::cin >> n >> a;
            p[n] += a;
        }
    }

    //{系数, 指数}
    std::vector<std::pair<double, int>> ans;
    for (int i = 1000; i >= 0; i--) {
        //fabs()用于把double类型的变量取绝对值
        if (fabs(p[i]) > 0) {
            ans.push_back({p[i], i});
        }
    }

    std::cout << ans.size();
    for (auto& [q, n] : ans) {
        //可以在前面先输出一个空格,这样就解决了结尾空格的问题
        std::cout << " " << n << " ";
        std::cout << std::fixed << std::setprecision(1) << q;
    }
}

题目1003:Emergency

题目大意:

现在有一个无向图,无向图每个节点表示一个城市,每个城市有若干个救援队员,每到一个城市就会召集这个城市的所有救援队员。

现在从某个节点c1出发,到达c2。保证c1到c2至少有一条路径,现在需要求出c1到c2的最短路径的数量,以及能得到的最大救援队员数量。

解题思路:

比较基础的dijstra算法模板题,这里没有太多细节,注意实现思路就好。

首先是我们要知道最短路线数量,我们可以建立一个数组std::vector<int> road(n, 0),road[u]表示从起点s到u的最短路线数量

还需要知道最大救援队的数量,那么我们可以建立一个数组std::vector<int> cnt(n, 0), cnt[u]表示从起点s到u,最短路径的同时的最大救援队数量。


现在进行dijstra算法,设此时的节点是u, 遇到一个新节点v,有两种情况:

情况1:最短路长度更小,那么我们的road[v] = road[u],找到了更短的路(或者说找到了新节点),直接继承road[u]。

救援队数量cnt[v] = cnt[u] + team[v],遇到了更短的路线,那么直接加上次节点的救援队数量即可
情况2:最短路长度相同,那么走到节点v的最短路线数量要加上走到u的最短路线数量。

cnt[v] += cnt[u]

我们目标是要获取尽可能多的救援队数量,我们需要比较一下两种路线的救援队数量,新节点v的救援队数量是cnt[v] ,如果我们从u走到v,救援队数量是cnt[u] + team[v],比较一下这两个即可

具体实现细节可以参考代码~

代码(C++):

cpp 复制代码
#include <bits/stdc++.h>

using i64 = long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n, m, s, t;
    std::cin >> n >> m >> s >> t;

    struct E {
        int to, w;
    };

    std::vector<int> team(n);
    for (int& x : team) {
        std::cin >> x;
    }

    std::vector<std::vector<E>> g(n);
    for (int i = 0; i < m; i++) {
        int u, v, w;
        std::cin >> u >> v >> w;
        g[u].push_back({v, w});
        g[v].push_back({u, w});
    }

    std::vector<i64> road(n, 0); //从起点s到节点u的最短路径数量road[u]
    std::vector<int> cnt(n, 0); //从起点s到节点u,最短路的情况下,最大的救援队数量cnt[u]
    std::vector<int> dist(n, 2e9); //dist[u]表示从起点s出发到节点u的最短距离

    using P = std::pair<int, int>; //{d, u}到节点u距离d
    std::priority_queue<P, std::vector<P>, std::greater<P>> pq;
    
    dist[s] = 0;
    road[s] = 1;
    cnt[s] = team[s];
    pq.push({0, s});

    while (!pq.empty()) {
        auto [d, u] = pq.top();
        pq.pop();
        if (d > dist[u]) {
            continue;
        }

        for (auto [v, w] : g[u]) {
            int nd = dist[u] + w;
            if (nd < dist[v]) {
                dist[v] = nd;
                road[v] = road[u];
                cnt[v] = cnt[u] + team[v];
                pq.push({nd, v});
            } else if (nd == dist[v]) {
                road[v] += road[u];
                int cur = cnt[u] + team[v];
                if (cur > cnt[v]) {
                    cnt[v] = cur;
                }
            }
        }
    }

    std::cout << road[t] << " " << cnt[t];
}

题目1004:Counting Leaves

题目大意:

现在给你一颗树,从根节点开始,一层一层的往下统计,统计每一层中没有孩子节点的节点数量

解题思路:

BFS的基础题,使用BFS从根节点开始一层一层的往下进行遍历。

具体实现的时候,我们可以建立一个**std::queue<std::pair<int, int>> q;**用来存节点和此时的深度d。

在遍历的过程中,如果此节点u的g[u]是空的,就表示没有孩子节点。BFS遍历的过程中,如果发现深度发生变化,那么就记录此时的没有孩子节点的节点数量,存在答案数组里面。

具体实现细节可以查看代码

代码(C++):

cpp 复制代码
#include <bits/stdc++.h>

using i64 = long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n, m;
    std::cin >> n >> m;

    std::vector<std::vector<int>> g(100);
    for (int i = 0; i < m; i++) {
        std::string s;
        std::cin >> s;
        int ID = std::stoi(s);
        int k;
        std::cin >> k;
        for (int j = 0; j < k; j++) {
            std::cin >> s;
            g[ID].push_back(std::stoi(s));
        }
    }

    std::vector<int> ans;
    std::queue<std::pair<int, int>> q;
    q.push({1, 1}); //{1, 1}表示一开始从根节点1开始遍历,开始的时候深度是d
    int cnt = 0; //没有孩子节点的节点数量
    int lv = 1; //层
    
    while (!q.empty()) {
        auto [u, d] = q.front();
        q.pop();

        if (d != lv) { //层发生了变化
            ans.push_back(cnt);
            lv++;
            cnt = 0;
        }
        if (g[u].empty()) {
            cnt++;
        }
        for (auto v : g[u]) {
            q.push({v, d + 1});
        }
    }
    //最后一层也要添加进来
    ans.push_back(cnt);

    for (int i = 0; i < ans.size(); i++) {
        std::cout << ans[i];
        if (i != ans.size() - 1) {
            std::cout << " ";
        }
    }
}

题目1005:Spell It Right

题目大意:

给出一个数字N,这个N的范围是[0, 1e100]

求出N的各个位数和,答案用英文表示出来

比如输入12345,位数和为15,你需要把答案表示成one five

解题思路:

这个题首先就可以用字符串存数字,然后把各个位数和加起来,设置为sum

那我们怎么快速的把答案用英文表示出来呢?

我们把sum再转换成成字符串,建立一个数组std::vector<std::string> arr = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};

然后就快速实现,具体实现细节可以看代码

代码(C++):

cpp 复制代码
#include <bits/stdc++.h>

using i64 = long long;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    std::string s;
    std::cin >> s;

    int sum = 0;
    for (char& c : s) {
        sum += c - '0';
    }

    std::vector<std::string> arr = {
        "zero",
        "one",
        "two",
        "three",
        "four",
        "five",
        "six",
        "seven",
        "eight",
        "nine"
    };

    std::string ans = "";
    for (char c : std::to_string(sum)) {
        int num = c - '0';
        ans += arr[num];
        ans += " ";
    }
    ans.pop_back();//把最后一个空格删掉

    std::cout << ans;
}
相关推荐
ZhengEnCi2 小时前
M5-markconv自定义CSS样式指南 📝
前端·css·python
ZhengEnCi2 小时前
M4-更新日志v0.1.3-Mermaid图表支持 📝
python
hsjcjh2 小时前
多模态长文本协同:用Gemini 3.1 Pro镜像官网破解复杂办公场景的效率困局(国内实测方案)
python
凯瑟琳.奥古斯特2 小时前
SQLAlchemy核心功能解析
开发语言·python·flask
卷Java2 小时前
GPTQ vs AWQ vs GGUF:模型量化工具横向测评
开发语言·windows·python
极客智造3 小时前
C++ 标准 IO 流全详解:cin /cout/get /getline 原理、用法、区别与避坑
c++·io
charlie1145141913 小时前
嵌入式C++工程实践第20篇:GPIO 输入模式内部电路 —— 芯片是如何“听“到外部信号的
开发语言·c++·stm32·单片机
念恒123064 小时前
Python(复杂判断)
python·学习
无敌的黑星星4 小时前
Java8 CompletableFuture 实战指南
linux·前端·python