PAT甲级2021秋季题解
前言
此次PAT甲级的题目较往年来说比较简单,以下给出2021秋季PAT甲级部分的题目大意(甲级题目为全英)以及个人的解题思路(不一定最优),放出的源码由于是写博客期间按照当时的思路进行复现的,所以不能保证完全正确,更多希望起到提供思路的作用
Arrays and Linked Lists (20p)
题目大意:用连续数组来模拟链表,给出一些连续数组的首址以及长度,默认数组元素为 int(sizeof = 4),多组输入样例,每次输入为想访问的元素下标,如果输入的元素下标合法(即在已给出的数组元素个数内),则输出其所在的地址,否则输出Illegal Acces,最后一行输出整个过程中申请的连续数组的个数
解题思路: 按照题意进行模拟即可,先进行预处理,用数组存储“链表”中每个节点的地址,查询时输出对应的值即可,有一个坑点在于,如果所有的输出样例都不合法,最后输出的声明连续数组的个数仍为1(我认为这是题意的bug,恐怕这也是大部分同学97分的原因)
源码:
#include<bits/stdc++.h>
using namespace std;
#define MAXSIZE 10000010
vector<pair<int,int>> inp;
int adr[MAXSIZE];
int rec[MAXSIZE];
int n,k,itp1,itp2,cnt,res = 1;
int main(){
cin >> n >> k;
for(int i=0;i<n;++i){
cin >> itp1 >> itp2;
inp.push_back(make_pair(itp1,itp2));
}
for(int i=0;i<n;++i){
for(int j=0;j<inp[i].second;++j){
adr[cnt] = inp[i].first + j*(sizeof(int));
rec[cnt] = i+1;
++cnt;
}
}
while(k--){
cin >> itp1;
if(itp1 < cnt){
cout << adr[itp1] << endl;
res = max(res,rec[itp1]);
}
else
cout << "Illegal Access" << endl;
}
cout << res << endl;
return 0;
}
Stack of Hats (25p)
题目大意: 假设有一个帽子堆,不同尺寸的帽子对应不同体型的PATer(大对大,小对小),现在给出这个帽子堆顺序的帽子尺寸(尺寸唯一),同时给出每个人的体重,输出按照帽子堆取帽子时PATer的体重顺序
解题思路: 比较简单的一道题,分别对帽子尺寸和体重排序后,用map存储其对应关系,最后按照对应的顺序输出即可
源码:
#include<bits/stdc++.h>
using namespace std;
vector<int> hat;
vector<int> per;
vector<int> tmp;
unordered_map<int,int> f;
int n,itp;
int main(){
cin >> n;
for(int i=0;i<n;++i){
cin >> itp;
hat.push_back(itp);
}
tmp = hat;
for(int i=0;i<n;++i){
cin >> itp;
per.push_back(itp);
}
sort(hat.begin(),hat.end());
sort(per.begin(),per.end());
for(int i=0;i<n;++i)
f[hat[i]] = per[i];
for(int i=tmp.size()-1;i>=0;--i){
if(i!=tmp.size()-1)
cout << " ";
cout << f[tmp[i]];
}
return 0;
}
Playground Exploration (25p)
题目大意: 给出一个无向图,任选一个起点出发,要求每一步在可选的路线中选择目标点下标最小的那条路线,不允许重复访问节点,按照这样的法则进行选择,问哪个点作为起始点时,可以访问的点尽可能的多,并输出起始点坐标以及可访问节点的数量
解题思路: 较为简单的一道dfs题目,当然不采用dfs也是可以做的
源码:
#include<bits/stdc++.h>
using namespace std;
int n,m,itp1,itp2;
bool mps[110][110];
bool vis[110];
int rp = -1,rb;
int rd;
void dfs(int beg){
vis[beg] = true;
rd++;
for(int i=1;i<=n;++i){
if(vis[i])
continue;
if(mps[beg][i]){
dfs(i);
break;
}
}
}
int main(){
cin >> n >> m;
for(int i=0;i<m;++i){
cin >> itp1 >> itp2;
mps[itp1][itp2] = mps[itp2][itp1] = true;
}
for(int i=1;i<=n;++i){
memset(vis,0,sizeof(vis));
rd = 0;
dfs(i);
if(rd > rp){
rb = i;
rp = rd;
}
}
cout << rb << " " << rp;
return 0;
}
Sorted Cartesian Tree (30p)
题目大意: 给定一个二叉树,二叉树中的每个节点由key和priority的两个整形元素构成,这棵树中每个节点的priority值满足小顶堆性质,而当对这棵树进行中序遍历时,得到的key值序列是从小到大的,现在给出这棵树上节点的集合,要求分别输出这棵树层序遍历的key值和priority值
解题思路: PAT甲级题库中常见的套路,根据树的某几种遍历序列建树,对已经得到的节点集合按照key值进行排序,即可得到中序序列,而在某个特定的中序序列中,priority值最小的那个节点对应的一定是该子树的根节点,按照此种方法即可完成建树,接着用bfs求出层序序列即可
源码:
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e9;
struct node{
int k;
int p;
node(){};
node(int a,int b){
k = a;
p = b;
}
};
struct t_node{
node val;
t_node* l;
t_node* r;
};
int n,itp1,itp2;
t_node* tree;
vector<node> nvs;
bool cmp(node& n1,node& n2){
return n1.k < n2.k;
}
t_node* build(int beg,int end){
if(end < beg)
return nullptr;
t_node* tmp = new t_node;
int minp = MAXN,minx = -1;
for(int i=beg;i<=end;++i){
if(nvs[i].p < minp){
minp = nvs[i].p;
minx = i;
}
}
tmp->val = node(nvs[minx].k,nvs[minx].p);
tmp->l = build(beg,minx-1);
tmp->r = build(minx+1,end);
return tmp;
}
queue<t_node*> que;
void bfs(t_node* beg){
que.push(beg);
while(!que.empty()){
t_node* tmp = que.front();
que.pop();
nvs.push_back(tmp->val);
if(tmp->l) que.push(tmp->l);
if(tmp->r) que.push(tmp->r);
}
}
int main(){
cin >> n;
for(int i=0;i<n;++i){
cin >> itp1 >> itp2;
nvs.push_back(node(itp1,itp2));
}
sort(nvs.begin(),nvs.end(),cmp);
tree = build(0,n-1);
nvs.clear();
bfs(tree);
for(int i=0;i<n;++i){
if(i!=0)
cout << " ";
cout << nvs[i].k;
}
cout << endl;
for(int i=0;i<n;++i){
if(i!=0)
cout << " ";
cout << nvs[i].p;
}
return 0;
}