PAT甲级2019冬季真题题解

题目及源代码下载:PAT甲级2019冬真题及题解

A Good in C

  字符串题,开一个三维数组char型,第一维大小为26,为26个字母,后面两维是存放表示该字母的7*5字符。后面使用getline读入一行,按照单词输出,注意细节,比如最后不能有多余的空行等等。

#include<cstdio>
#include<iostream>
#include<string>

using namespace std;
char arr[26][7][6];
string s;
//输出字符串
void call(const string &s) {
    //7行
    for (int i = 0; i < 7; i++) {
        for (int j = 0; j < s.length(); j++) {
            printf("%5s", arr[s[j] - 'A'][i]);
            if (j != s.length() - 1)
                printf(" ");
        }
        if (i != 6)
            printf("\n");
    }
}

int main() {
    for (int i = 0; i < 26; i++) {
        for (int j = 0; j < 7; j++) {
            scanf("%s", arr[i][j]);
        }
    }
    //削除换行符
    getchar();
    getline(cin, s);
    int pos = 0, pre;
    bool op = false;
    while (pos < s.length()) {
    	//消除非大写字母
        while (pos < s.length() && !(s[pos] >= 'A' && s[pos] <= 'Z'))
            ++pos;
        //到行末,则退出
        if (pos == s.length())
            break;
        pre = pos;
		//遍历单词有边界
        while (pos < s.length() && s[pos] >= 'A' && s[pos] <= 'Z')
            ++pos;
        //每行单词之间有个空行
        if (op)
            printf("\n\n");
        op = true;
        call(s.substr(pre, pos - pre));
    }
    return 0;
}

B Block Reversing

  数据结构题,考的是链表,要习惯数组模拟链表的算法,建议多刷刷力扣的数据结构,刚上手还是很难理解的,下面那4行代码是核心,理解起来还是挺费劲的。

#include<iostream>

using namespace std;
const int MAXN = 1000010;
int val[MAXN], nxt[MAXN];
int head, n, k;

int main() {
    int address;

    cin >> head >> n >> k;
    for (int i = 0; i < n; i++) {
        cin >> address;
        cin >> val[address] >> nxt[address];
    }

    int pre = -1;
    while (head != -1) {
    	//记录头
        int tmp = head;
        //找到一个block的末尾
        for (int i = 0; i < k - 1; i++) {
            if (nxt[head] == -1)
                break;
            head = nxt[head];
        }
        //暂存下一个block的头
        int tt = nxt[head];
        //末尾接到上一个的头
        nxt[head] = pre;
        //更新pre为当前头
        pre = tmp;
        //考虑下一个block
        head = tt;
    }
    while (pre != -1) {
        if (nxt[pre] != -1)
            printf("%05d %d %05d\n", pre, val[pre], nxt[pre]);
        else
            printf("%05d %d -1", pre, val[pre]);
        pre = nxt[pre];
    }
    return 0;
}

C Summit

  图论,或许比B题简单,N最大为200,直接使用邻接矩阵存储,然后根据题意编程即可,也算道模拟题吧,没有多少算法的部分。

#include<iostream>

#define ac cin.tie(0);cin.sync_with_stdio(0);
using namespace std;
const int MAXN = 210;
bool G[MAXN][MAXN];
int arr[MAXN];
int n, m, k;

int main() {
    ac
    int a, b, len;

    cin >> n >> m;
    while (m--) {
        cin >> a >> b;
        G[a][b] = G[b][a] = true;
    }

    cin >> k;
    for (int cas = 1; cas <= k; cas++) {
        cin >> len;
        for (int i = 0; i < len; i++)
            cin >> arr[i];
        bool op = true;
        for (int i = 0; i < len; i++)
            for (int j = i + 1; j < len; j++)
            //有两个人不是朋友
                if (!G[arr[i]][arr[j]]) {
                    op = false;
                    break;
                }
        if (!op)
            cout << "Area " << cas << " needs help.";
        else {
            op = true;
            for (int i = 1; i <= n; i++) {
                bool p = true;
                for (int j = 0; j < len; j++) {
                //已经在集合中了,跳过
                    if (i == arr[j]) {
                        p = false;
                        break;
                    }
                    //有不认识的人,跳过
                    if (!G[i][arr[j]]) {
                        p = false;
                        break;
                    }
                }
                //有一个人和集合所有人是朋友,满足条件
                if (p) {
                    cout << "Area " << cas << " may invite more people, such as " << i << ".";
                    op = false;
                    break;
                }
            }
            if (op)
                cout << "Area " << cas << " is OK.";
        }
        if (cas != k)
            cout << endl;
    }
    return 0;
}

D Cartesian Tree

  算法模板题,和根据中序和前序或后序建树类似,但是这个树其实还是个最小堆,然后层序遍历输出结果,要熟悉树的数组写法。

#include<iostream>
#include<climits>

#define ac cin.tie(0);cin.sync_with_stdio(0);

using namespace std;
const int MAXN = 40;
int le[MAXN], ri[MAXN], val[MAXN], arr[MAXN];
int n, cnt;
//建树
int dfs(int a, int b) {
    if (a > b)
        return -1;

    int v = INT_MAX, pos;
    //找到最小的节点
    for (int i = a; i <= b; i++)
        if (arr[i] < v) {
            v = arr[i];
            pos = i;
        }
    int tmp = cnt;
    ++cnt;
    val[tmp] = v;
    le[tmp] = dfs(a, pos - 1);
    ri[tmp] = dfs(pos + 1, b);
    return tmp;
}

int main() {
    ac
    cin >> n;
    for (int i = 0; i < n; i++)
        cin >> arr[i];

    int root = dfs(0, n - 1);
	//层序遍历输出结果
    int tt = 0, hh = 0;
    arr[0] = root;
    while (tt <= hh) {
        int cur = arr[tt++];
        if (cur)
            cout << " ";
        cout << val[cur];
        if (le[cur] != -1)
            arr[++hh] = le[cur];
        if (ri[cur] != -1)
            arr[++hh] = ri[cur];
    }
    return 0;
}

最后附一张图,希望一周后的冬季考试也这样简单 ><
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值