题目及源代码下载: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;
}
最后附一张图,希望一周后的冬季考试也这样简单 ><