2019.12.07考PAT的一些想法和总结

期末考试结束了,总结一下上次考的PAT,也就是2019/12/07的那一次。说起考PAT,是我以前的一个室友带着我一起考的,他想考浙大的研究生,我主要是想锻炼一下自己的能力,应付考研的机试,但不是考浙大。

小结:这次考了80分,第一个HelloWorld没做,有点可惜,好像这次有一百五十几个满分的把,不知道是一个考场的还是全国的。第一次考心里有些紧张,其实做题的时候是有思路的,但是在考场上光调试就花了很长时间。平时练习的时候挺好的,到现场做题感觉完全不同,就感觉很慌张。我觉得还是临场发挥能力不行,这次考试我debug出现的错误最多的就是越界的错误了,还有就是在考试的时候不能直接复制粘贴,那个HelloWorld粘的我头疼,只能在黑框框上面选项里面粘贴。总结一句话准备不够充分!!!

考试当天的经历:早上七点三十分起床,到咸宁的高铁站差不多已经8.30了把,然后中途转了几趟车到武汉科技大学的黄家湖校区估计10点左右,中途碰到了一起考PAT的小伙伴。去了之后先找考场,发现计算机学院负责的阿姨居然都不知道这个考试,问本校学生也是不知道,无奈去吃了个午饭。回来的时候上面就贴了告示,然后就跑到考试的四楼去。去的时候没啥人,看了自己的考场位置,然后才陆陆续续的来了一些人。进考场找自己的座位,ABC和数字组合的都是乱的,找了好久找到了自己的座位,一坐下来,旁边的大哥就已经开始劈里啪啦的敲击键盘了,搞的我有点小紧张。我还没开始考试,隔壁的一位老哥就被驱逐考场了,说是打开了浏览器,搞得我小心翼翼,生怕碰到维基百科的解释。写题的时候是从后往前面写的,看了好多大佬经验贴才这样做的,最后一题是说的时候一个最小堆,看着不会,然后跳过看其他的题目去了,倒数第二题好像是一个最大团的问题,这个考之前还看了的,写完之后,一运行就很多错误,调试了半天也没搞出来,最后又去做第二题,第二题是一个置换块的问题,那个是对把给定数字的块进行整体置换,还比较简单,正序输入,倒叙输出,就是输出结果一直不对,也是debug了好久,最后写出来了,然后写第三题和第四题。就这样AC了题,写第一题只有十几分钟了。然后一直对照着输入看输出,发现就是打印对应的字母,最后用三重数组做,然后宣告失败!!!就这样80分结束了,考完过了半小时领完成绩单,就回学校了。

真题:

第一题:

7-1 Good in C (20分)

When your interviewer asks you to write "Hello World" using C, can you do as the following figure shows?

HWC.jpg

Input Specification:

Each input file contains one test case. For each case, the first part gives the 26 capital English letters A-Z, each in a 7×5 matrix of C's and .'s. Then a sentence is given in a line, ended by a return. The sentence is formed by several words (no more than 10 continuous capital English letters each), and the words are separated by any characters other than capital English letters.

It is guaranteed that there is at least one word given.

Output Specification:

For each word, print the matrix form of each of its letters in a line, and the letters must be separated by exactly one column of space. There must be no extra space at the beginning or the end of the word.

Between two adjacent words, there must be a single empty line to separate them. There must be no extra line at the beginning or the end of the output.

Sample Input:

..C..
.C.C.
C...C
CCCCC
C...C
C...C
C...C
CCCC.
C...C
C...C
CCCC.
C...C
C...C
CCCC.
.CCC.
C...C
C....
C....
C....
C...C
.CCC.
CCCC.
C...C
C...C
C...C
C...C
C...C
CCCC.
CCCCC
C....
C....
CCCC.
C....
C....
CCCCC
CCCCC
C....
C....
CCCC.
C....
C....
C....
CCCC.
C...C
C....
C.CCC
C...C
C...C
CCCC.
C...C
C...C
C...C
CCCCC
C...C
C...C
C...C
CCCCC
..C..
..C..
..C..
..C..
..C..
CCCCC
CCCCC
....C
....C
....C
....C
C...C
.CCC.
C...C
C..C.
C.C..
CC...
C.C..
C..C.
C...C
C....
C....
C....
C....
C....
C....
CCCCC
C...C
C...C
CC.CC
C.C.C
C...C
C...C
C...C
C...C
C...C
CC..C
C.C.C
C..CC
C...C
C...C
.CCC.
C...C
C...C
C...C
C...C
C...C
.CCC.
CCCC.
C...C
C...C
CCCC.
C....
C....
C....
.CCC.
C...C
C...C
C...C
C.C.C
C..CC
.CCC.
CCCC.
C...C
CCCC.
CC...
C.C..
C..C.
C...C
.CCC.
C...C
C....
.CCC.
....C
C...C
.CCC.
CCCCC
..C..
..C..
..C..
..C..
..C..
..C..
C...C
C...C
C...C
C...C
C...C
C...C
.CCC.
C...C
C...C
C...C
C...C
C...C
.C.C.
..C..
C...C
C...C
C...C
C.C.C
CC.CC
C...C
C...C
C...C
C...C
.C.C.
..C..
.C.C.
C...C
C...C
C...C
C...C
.C.C.
..C..
..C..
..C..
..C..
CCCCC
....C
...C.
..C..
.C...
C....
CCCCC
HELLO~WORLD!

Sample Output:

题意:给定A-Z的字母表示,用一个7*5的矩阵表示的,然后根据最后一个字符串输出,碰到不是大写字母就表示是一个单词,输出对应的单词矩阵。

思路:虽然当时没做出来,事后写了一下,不知道是不是正确的,但是样例能够通过。用一个vector的二维数组保存A-Z的字母矩阵,然后再把给定的一句话进行切割,分成每个单词,然后对单词进行输出,注意对单词输出的格式以及顺序,单词是横着打印的。

代码:

#include<iostream>
#include<string>
#include<vector>
using namespace std;
vector<vector<string>> v(100);
int findcap(string s,int beg,int des) {
	int index = des,flag = 0;
	for (int i = beg; i < des; i++) {//找出第一个不为大写字母的索引
		if (s[i]<'A' || s[i]>'Z') {
			index = i; 
			flag = 1;
			break;
		}
	}
	return flag == 1 ? index : -1;
}
int main() {
	string str;
	for (int i = 0; i < 26; i++) {
		v[i].resize(7);
		for (int j = 0; j < 7; j++) {
			getline(cin,str);
			v[i][j] = str;
		}
	}
	string s;
	cin >> s;
//	printf("***********************************************************************\n");
	vector<string> word;//保存每个单词
	int index = 0;
	while (index < s.size()) {//找出每个的单词
		int i = findcap(s, index, s.size()) - index;
		if (i != -1) {
			word.push_back(s.substr(index, i));
			index = index + i + 1;
		}
	}
	index = 0;
	for (int k = 0; k < word.size(); k++) {//打印每个单词
		for (int i = 0; i < 7; i++) {//控制打印单词中每个字母打印的行数
			for (int j = 0; j < word[k].size(); j++) {//每个字母第i行表示
				int num = word[k][j] - 'A';//表示第k个单词的j个字母
				printf("%s%s", v[num][i].c_str(), j == word[k].size() - 1 ? "\n" : " ");
			}
		}
	}
	system("pause");
	return 0;
}

截图: 

第二题:

7-2 Block Reversing (25分)

Given a singly linked list L. Let us consider every K nodes as a block (if there are less than K nodes at the end of the list, the rest of the nodes are still considered as a block). Your job is to reverse all the blocks in L. For example, given L as 1→2→3→4→5→6→7→8 and K as 3, your output must be 7→8→4→5→6→1→2→3.

Input Specification:

Each input file contains one test case. For each case, the first line contains the address of the first node, a positive N (≤10​5​​) which is the total number of nodes, and a positive K (≤N) which is the size of a block. The address of a node is a 5-digit nonnegative integer, and NULL is represented by −1.

Then N lines follow, each describes a node in the format:

Address Data Next

where Address is the position of the node, Data is an integer, and Next is the position of the next node.

Output Specification:

For each case, output the resulting ordered linked list. Each node occupies a line, and is printed in the same format as in the input.

Sample Input:

00100 8 3
71120 7 88666
00000 4 99999
00100 1 12309
68237 6 71120
33218 3 00000
99999 5 68237
88666 8 -1
12309 2 33218

Sample Output:

71120 7 88666
88666 8 00000
00000 4 99999
99999 5 68237
68237 6 00100
00100 1 12309
12309 2 33218
33218 3 -1

 题意:从起始地址开始,每K个元素逆置,也就是说交换的单位是以K个元素进行交换的。

思路:按给定的首地址开始依次把所有的节点加入数组,然后从最后一个封闭区开始输出,即进行了交换。

代码:

#include<iostream>
#include<vector>
using namespace std;
struct no {
	int id,data, next;
}node[100010];
int main() {
	int fir, n, k,cnt,tem,index = 0;//cnt表示有多少个这样的封闭区
	cin >> fir >> n >> k;
	if (n / k == 0)cnt = n / k;
	else cnt = n / k + 1;
	vector<vector<no>> v(cnt);//v实际保存地址
	for (int i = 0; i < n; i++) {//s输入
		scanf("%d",&tem);
		node[tem].id = tem;
		scanf("%d%d",&node[tem].data, &node[tem].next);
	}
	int p = fir;
	vector<no> q;
	for (int i = p; i != -1; i = node[i].next) {
		q.push_back(node[i]);
	}
	tem = 0;
	for (int i = 0; i < q.size(); i++) {
		if (tem == k) {
			tem = 0;
			index++;
		}
		v[index].push_back(q[i]);
		tem++;
	}
	for (int i = v.size() - 1; i >= 0; i--) {
		for (int j = 0; j < v[i].size(); j++) {
			printf("%05d %d ", v[i][j].id, v[i][j].data);
			if (j != v[i].size()-1)printf("%05d\n", v[i][j].next);
			else if(j==v[i].size()-1&&i!=0){
				printf("%05d\n", v[i-1][0].id);
			}
			else {
				printf("-1\n");
			}
		}
	}
	system("pause");
	return 0;
}

截图:

打印格式注意一下。

第三题: 

7-3 Summit (25分)

summit (峰会) is a meeting of heads of state or government. Arranging the rest areas for the summit is not a simple job. The ideal arrangement of one area is to invite those heads so that everyone is a direct friend of everyone.

Now given a set of tentative arrangements, your job is to tell the organizers whether or not each area is all set.

Input Specification:

Each input file contains one test case. For each case, the first line gives two positive integers N (≤ 200), the number of heads in the summit, and M, the number of friendship relations. Then M lines follow, each gives a pair of indices of the heads who are friends to each other. The heads are indexed from 1 to N.

Then there is another positive integer K (≤ 100), and K lines of tentative arrangement of rest areas follow, each first gives a positive number L (≤ N), then followed by a sequence of L distinct indices of the heads. All the numbers in a line are separated by a space.

Output Specification:

For each of the K areas, print in a line your advice in the following format:

  • if in this area everyone is a direct friend of everyone, and no friend is missing (that is, no one else is a direct friend of everyone in this area), print Area X is OK..

  • if in this area everyone is a direct friend of everyone, yet there are some other heads who may also be invited without breaking the ideal arrangement, print Area X may invite more people, such as H. where H is the smallest index of the head who may be invited.

  • if in this area the arrangement is not an ideal one, then print Area X needs help. so the host can provide some special service to help the heads get to know each other.

Here X is the index of an area, starting from 1 to K.

Sample Input:

8 10
5 6
7 8
6 4
3 6
4 5
2 3
8 2
2 7
5 3
3 4
6
4 5 4 3 6
3 2 8 7
2 2 3
1 1
2 4 6
3 3 2 1

Sample Output:

Area 1 is OK.
Area 2 is OK.
Area 3 is OK.
Area 4 is OK.
Area 5 may invite more people, such as 3.
Area 6 needs help.

题意:此题是一个最大团的问题,给定一个无向图,然后在给定一个集合,首先判断该集合是否是一个最大的团,如果是的话打印OK,否则就判断除此集合外所有的点中是否仍然能够加入该集合,加入的要求是该点能够与集合中的所有点相邻。如果该集合含有与除此点外所有点不相邻的情况,则打印need help。

思路:首先用一个邻接表建立一个无向图,然后检查该集合是否有need help的情况出现,首先对此情况进行判断,然后判断除集合中的人以外是否还有人可以加入此集合,如果是则满足第二种情况,如果没有则是OK的。

代码:

#include<iostream>
#include<algorithm>
#include<vector>
#define INF 65536
int g[300][300] = {0},flag = 1;//初始化代表所有的点都不相连
using namespace std;
void check(vector<int> p) {
	for (int i = 0; i < p.size(); i++) {//检查团中的点是否与其他相邻
		for (int j = i + 1; j < p.size(); j++) {
			if (g[p[i]][p[j]] == 0) {
				flag = 0;
				return;
			}
		}
	}
}
int main() {
	int n, m, k,a, b,num;
	cin >> n >> m;
	for (int i = 0; i < m; i++) {
		scanf("%d%d",&a,&b);
		g[a][b] = g[b][a] = 1;
	}
	cin >> k;
	for (int v = 1; v <= k; v++) {
		scanf("%d", &num);
		flag = 1;
		vector<int> p(num);
		bool vis[300];
		fill(vis, vis + 300, false);
		for (int i = 0; i < num; i++) {//输入数据
			scanf("%d", &p[i]);
			vis[p[i]] = true;
		}
		flag = 1;
		check(p);//判断是否集合是否需要帮助
		if (flag == 0) {
			printf("Area %d needs help.\n", v);
			continue;
		}
		flag = 1;
		for (int i = 1; i <= n; i++) {//检查每个不是团中的点是否与团直接相邻
			if (vis[i] == false) {
				for (int j = 0; j < p.size(); j++) {
					if (g[i][p[j]] == 0)break;//只要一个不相邻就不是了
					if (j == p.size() - 1) {
						flag = 0;
						printf("Area %d may invite more people, such as %d.\n",v,i);
						break;
					}//表示还有点位加入
				}
			}
			if (flag == 0)break;//找到一个多余的人就可以了
		}
		if (flag == 1) {
			printf("Area %d is OK.\n", v);
		}
	}
	system("pause");
	return 0;
}

截图:

第四题:

7-4 Cartesian Tree (30分)

Cartesian tree is a binary tree constructed from a sequence of distinct numbers. The tree is heap-ordered, and an inorder traversal returns the original sequence. For example, given the sequence { 8, 15, 3, 4, 1, 5, 12, 10, 18, 6 }, the min-heap Cartesian tree is shown by the figure.

CTree.jpg

Your job is to output the level-order traversal sequence of the min-heap Cartesian tree.

Input Specification:

Each input file contains one test case. Each case starts from giving a positive integer N (≤30), and then N distinct numbers in the next line, separated by a space. All the numbers are in the range of int.

Output Specification:

For each test case, print in a line the level-order traversal sequence of the min-heap Cartesian tree. All the numbers in a line must be separated by exactly one space, and there must be no extra space at the beginning or the end of the line.

Sample Input:

10
8 15 3 4 1 5 12 10 18 6

Sample Output:

1 3 5 8 4 6 15 10 12 18

 题意:此题主要是比较难以理解,想明白了还是比较容易的一题,求给定 一个序列的最小堆的层序遍历,可以建树也可以不建树,主要思想就是最小堆的概念,根节点比左右孩子都小。

思路:根据最小堆的概念,根节点的比左右孩子的值都要小,首先找最小的值,定位根节点,然后从此节点左边找次小的点,作为左孩子,在从右边找次小的点,作为右孩子。依次下去,建树的思想也是一样的。不建数的话就是直接中序遍历,给所有的点的层次和下标赋值,用于排序,建树层次遍历可能会简单一点。

代码:

#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
vector<int> v;
map<int, int> pos;
struct node {
	int data,level,index;
};
int findmin(vector<int> p, int left, int right) {//找出给定范围的最小值
	int min = 9999999;
	for (int i = left; i <= right; i++) {
		if (p[i] < min) {
			min = p[i];
		}
	}
	return min;
}
vector<node> ans;
void inorder(int root, int inL, int inR, int level, int index) {//中序遍历顺便给所有的节点的层次和下标赋值,用于排序
	if (inL >= inR) {
		ans.push_back(node{ root ,level,index });
		return;
	}
	int nextroot1 = findmin(v, inL, pos[root] - 1);
	if (nextroot1 != 9999999) {
		inorder(nextroot1, inL, pos[root] - 1, level + 1, index * 2 + 1);
	}
	ans.push_back(node{ root ,level,index });
	int nextroot2 = findmin(v, pos[root] + 1, inR);
	if (nextroot2 != 9999999) {
		inorder(nextroot2, pos[root] + 1, inR, level + 1, index * 2 + 2);
	}
}
bool com(node a,node b) {//首先按层序先后排序然后按照下标排序
	if (a.level != b.level)return a.level < b.level;
	else return a.index < b.index;
}
int main() {
	int n;
	cin >> n;
	v.resize(n);
	for (int i = 0; i < n; i++) {
		scanf("%d", &v[i]);
		pos[v[i]] = i;
	}
	int root = findmin(v, 0, v.size()-1);
	inorder(root, 0, n - 1,0,0);
	sort(ans.begin(),ans.end(),com);
	for (int i = 0; i < ans.size(); i++) {
		printf("%d%s",ans[i].data,i==ans.size()-1?"\n":" ");
	}
	system("pause");
	return 0;
}

截图:

最后总结一下就是正确看待PAT考试,考前认真准备,考试中不要慌,自己写自己的。祝所有认真准备的都能通过! 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值