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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值