2023夏PAT甲级题解

目录

总结:

A-1

题意:

思路:

AC代码:

A-2 

题意:

AC代码:

A-3

题意:

思路:

A-4 Big Number

题意:

思路:

AC代码


总结:

        第一次打PAT甲级可能也是最后一次打了,可能因为今天蓝桥国赛,就我一个人考,考场上主要还是不太适应英文题面,老是看样例猜题意,第一个题一看是个地图乍以为是个搜索,读了20分钟题看懂题意是个模拟,交了一发13分,想不出来测试点,于是看第二题,看样例以为直接用队列就行了,沉下心看题目,结果要按题意双栈模拟队列,调试了20分钟AC了,第三题常规的建树,求每个节点的度,调试20分钟AC了,这时一看排名33。就接着看第四题,看样例和题意都没看懂,这时还有1个半小时结束,后面又排序骗了5分,最后又回去想第一题的测试点,测不出来。一个半小时坐牢,就这样结束了这次考试。

        赛后又补了下题,找队友一起读题读懂了A4, 还没测,以下代码是都是凭记忆写的,等过两天可以测题了,会再更新。

A-1

题意:

给定一个N*N的地图,地图上有障碍物,规定从最后一行走,即最后一行列为1~n的为起点,可以一直往上走,遇到障碍物后往左走,若往左走能走出边界则也算能走出去,求不能走出地图的起点为多少。

思路:

模拟,枚举每个起点即可

AC代码:

待补~

A-2 

题意:

给你两个栈,模拟一个队列,并且给出每次deque操作的时间。

AC代码:

#include 

#define all(s) s.begin(), s.end()

using namespace std;

const int N = 1e5 + 7;

string op;
int n, x, k;
stack s1, s2;

int main() {
    cin.tie(nullptr)->ios::sync_with_stdio(false);
    cin >> n;
    while (n -- ) {
        cin >> op;
        if (op == "I") {
            cin >> x;
            s1.push(x);
        } else {
            if (s1.empty() && s2.empty()) {
                cout << "ERROR\n";
                continue;
            }
            if (s2.empty()) {
                while (!s1.empty()) {
                    s2.push(s1.top());
                    s1.pop();
                    k += 2;
                }
            }
            cout << s2.top() << ' ' <<  ++ k << endl;
            k = 0;
            s2.pop();
        }
    }
    return 0;
}

A-3

题意:

给你一颗二叉树的先序遍历和中序遍历,求每个顶点的度。

思路:

递归建树,再进行从根节点dfs计算每个节点的度,注意节点范围在int,因此最好开个map。

#include 

using namespace std;

const int N = 1e3 + 7;

int n;
int inOrder[N], preOrder[N];
unordered_map mp, degree;

struct TreeNode {
    int val;
    TreeNode *left, *right;
    TreeNode(int x): val(x), left(nullptr), right(nullptr) {}
};

TreeNode *build(int inL, int inR, int preL, int preR) {
    if (inL > inR) return nullptr;
    int curRoot = preOrder[preL];
    auto *root = new TreeNode(curRoot);
    int k = mp[curRoot];
    root->left = build(inL, k - 1, preL + 1, preL + k - inL);
    root->right = build(k + 1, inR, preL + k - inL + 1, preR);
    return root;
}

void DFS(TreeNode *root) {
    if (!root) return ;
    if (root->left) {
        degree[root->val] ++;
        DFS(root->left);
    }
    if (root->right) {
        degree[root->val] ++;
        DFS(root->right);
    }
}

int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> inOrder[i], mp[inOrder[i]] = i;
    for (int i = 1; i <= n; i++) cin >> preOrder[i];
    TreeNode *root = build(1, n, 1, n);
    DFS(root);
    int n0 = 0, n1 = 0, n2 = 0;
    for (auto [k ,v] : mp) {
        if (degree[v] == 0) n0 ++;
        if (degree[v] == 1) n1 ++;
        if (degree[v] == 2) n2 ++;
    }
    cout << n0 << " * " << n1 << " / " << n2 << " = " << (int)(n0 * 1.0 * n1 / n2);
    return 0;
}

A-4 Big Number

这题当时考场上读了1小时没读懂题目,赛后问队友才明白题意。

题意:

给你n张卡牌,卡牌的一面写着索引(1-n)一面写着一位数的数字,这意味着n的若卡牌的一面为大于等于10的数字,则这个卡牌的索引和数字是确定的,若两面都为小于10的数字,则两面都可以互用,要求你按照索引给出最后拼成的最小的数字。

思路:

索引为10~n的数字是确定的,那么我们只考虑索引为1~9的即可,对于每个索引为1~9的我们找出当前可以放置的数字最小的,然后再把用过的这个边删掉即可。时间复杂度大概O(10 * (n + e))

AC代码

#include 

#define all(s) s.begin(), s.end()

using namespace std;

const int N = 1e5 + 7;

int n, a, b;
vector g[N];

int main() {
    cin.tie(nullptr)->ios::sync_with_stdio(false);
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> a >> b;
        if (a >= 10) swap(a, b); //索引是 y 数字是x
        if (a < 10 && b < 10) {
            g[a].push_back(b), g[b].push_back(a);
        } else if (a < 10 && b >= 10) {
            g[b].push_back(a);
        }
    }
    for (int i = 1; i <= n; i++) {
        if (i >= 10) cout << g[i][0];
        else {
            int minv = *min_element(all(g[i]));
            g[minv].erase(find(all(g[minv]), i));
            cout << minv;
        }
    }
    return 0;
}

你可能感兴趣的:(深度优先,算法,图论,c++)