2024年9月PAT甲级复盘

2024年9月PAT甲级

备考比较仓促,备考书籍:曾磊《算法笔记》,这本书上的题目与PAT相互对应,可以顺便熟悉出题思路。笔者被第二道题目的一句话卡到了,一直PA,费了很长时间在debug,最后一题草草了事,来不及做优化,考完买了题目集随便一优化就过了,本来应该可以满分的。下面我们来看一下题目吧。

A-1 Happy Patting

The “Happy Patting” game is to arrange the children into n rows, with m people in each row. When the game starts, each child will receive a digital command on his/her mobile phone simultaneously: 1 for forward, 2 for backward, 3 for left, and 4 for right. The children must follow the command to pat the children in the specified direction. How many children are patted by more than one friend?
Note: In the plane diagram, the top of a grid is “front” and the bottom is “back”. Children in the corners may pat the air, which is also allowed.

Input Specification:

Each input file contains one test case. The first line gives 2 positive integers n and m (2≤n,m≤100), which are the number of rows and the number of people in each row, respectively.
Then n lines follow, each contains m numbers, which represent the digital commands received by the children at the corresponding position.
All the numbers in a line are separated by a space.

Output Specification:

For each test case, print in a line the number of children who are patted by more than one friend.

input:
3 5
1 2 3 4 1
4 1 4 3 3
3 2 1 1 3
output:
4

题意:小朋友坐在一起,相互之间可以拍打(patting),1234分别表示该位置的小朋友往前后左右拍,问有多少个小朋友被拍了两次及以上。

思路:直接开个二维矩阵,记录每个位置被拍到的次数,最后遍历计数即可。

#include <iostream>
using namespace std;
int N, M;
int num[110][110] = { 0 };
int main()
{
	cin >> N >> M;
	int i, j;
	for (i = 1; i <= N; i++) {
		for (j = 1; j <= M; j++) {
			int a;
			cin >> a;
			if (a == 1) {
				num[i - 1][j]++;
			}
			else if (a == 2) {
				num[i + 1][j]++;
			}
			else if (a == 3) {
				num[i][j - 1]++;
			}
			else {
				num[i][j + 1]++;
			}
		}
	}
	int ans = 0;
	for (i = 1; i <= N; i++) {
		for (j = 1; j <= M; j++) {
			if (num[i][j] >= 2)ans++;
		}
	}
	cout << ans;
}

A-2 Baggage Carousel

When a flight arrives, the passengers will go to the Arrivals area to pick up their luggages from a baggage carousel(行李转盘).
Now assume that we have a special airport that has only one pickup window for each baggage carousel. The passengers are asked to line up to pick up their luggage one by one at the window. The carousel can hold at most m luggages, and each luggage has a unique tag number. When a passenger’s tag number is matched by a luggage on the carousel, the luggage is then handed to the passenger and the next luggage will be sent onto the carousel.
But if one arrives at the window yet finds out that one’s luggage is not on the carousel, one will have to move to the end of the queue and wait for the next turn. Suppose that each turn takes 1 minute, your job is to calculate the total time taken to clear the baggage carousel.

Input Specification:

Each input file contains one test case. The first line gives 2 positive integers n (≤500) and m (≤50), which are the number of passengers and the size of the baggage carousel, respectively.
Then n distinct tag number are given in the next line, each is an 8-digit number. The tag numbers are given in the order of being sent to the carousel. It is assumed that min(n,m) luggages are already on the carousel at the beginning.
The next line gives another sequence of n distinct tag numbers, which corresponds to the passengers in the queue.
All the numbers in a line are separated by a space.

Output Specification:

For each test case, print in a line the total time taken to clear the baggage carousel.
Note:
If the tag number of a passenger cannot be found at all, that means the passenger’s luggage is lost. In this case you must output in a line TagNumber is lost! where TagNumber is the tag number, and then remove this passenger from the queue right away. Since the number of luggages is the same as the number of passengers, if one passenger’s luggage is lost, there must be one luggage left and the carousel can never be cleared. In this case, output in the last line the total time taken to clear the passengers’ queue.

input:
10 4
00000001 00000002 00000003 00000004 00000005 00000006 00000007 00000008 00000009 00000010
00000010 00000008 00000006 00000001 00000004 00000007 00000003 00000009 00000005 00000002
output:
16

题意:模拟乘客取行李的过程,统计最终花费时间。注意若没有该乘客的行李则立即告知此乘客。

思路:将行李放在数组中,由于乘客成一队,将乘客放在队列中。将行李放入的同时,开一个contain的set,在后面乘客入队的同时看是否有乘客的行李不在转盘上,,若不在则将其id放入lost的set中;开一个Carousel的set,后面匹配上行李则erase掉。然后就模拟Time,直到队列为空。过程中匹配上行李则将乘客出队,在Carousel中erase掉,若发现乘客是lost中的,则将其出队并立即告知其行李lost(也就是这句话,我原本是将这些乘客信息保存起来,最后再进行输出,结果卡了我一个多小时才排查出来,原来是要发现则立即说出来)。

#include<iostream>
#include<queue>
#include<cstdio>
#include<set>
#include<math.h>
#include<vector>
using namespace std;
int N, M;
queue<int>q;
set<int>lost;
int baggage[600];
set<int>Carousel, contain;
int main() {
	cin >> N >> M;
	for (int i = 0; i < N; i++) {
		cin >> baggage[i];
		contain.insert(baggage[i]);
		if (i < M)Carousel.insert(baggage[i]);
	}
	for (int i = 0; i < N; i++) {
		int a; cin >> a;
		if (!contain.count(a))lost.insert(a);
		q.push(a);
	}
	int num = min(N, M), Time;
	for (Time = 0; !q.empty(); Time++) {
		if (Carousel.count(q.front())) {//匹配上
			Carousel.erase(q.front());
			if (num < N)Carousel.insert(baggage[num]);
			num++;
			q.pop();
		}
		else {//没匹配上,排到后面
			int now = q.front();
			q.pop();
			if (!lost.count(now))q.push(now);
			else{ printf("%08d is lost!\n", now); }
		}
	}
	printf("%d\n", Time);
}

A-3 Finding Independent Set

Given a simple undirected graph G=(V,E). An independent set of G is a set SV such that no two members of S are connected by an edge in E. Finding the maximum independent set of G is an NP-hard problem. Here you are supposed to implement a greedy hueristic to find a near-maximum independent set.
The algorithm works in the following way:

  1. Collect any one un-visited vertex v into S.
  2. Delete all the vertices (and all the edges incident on them) that are adjacent to v from G.
  3. Repeat steps 1 and 2 until there is no un-visited vertex left in G.

In order to obtain the unique solution, when there are many options in step 1, you must always choose the vertex with the smallest index.

Input Specification:

Each input file contains one test case. For each case, the first line contains 2 positive integers: n (≤1000), the number of vertices; and m, the number of edges. Then m lines follow, each gives indices of the two ends of an edge. The vertices are indexed from 1 to n.

Output Specification:

Print in a line the indices of the vertices in the independent set obtained by the given greedy algorithm. The indices must be in increasing order, and must be separated by exactly 1 space. There must be no extra space at the beginning or the end of the line.

input:
8 7
1 5
5 4
4 2
2 3
3 6
6 1
6 2
output:
1 2 7 8

题意:要实现一个independent set of G是一个NP问题,我们按照题目给出的操作来就可求出一个简单的独立集。

思路:用邻接表村图的信息,按照题目要求,就是从1号点开始将未访问过的点放入独立点集中,同时将邻接的点设置成已访问。最后将独立点集输出即可。点击提交后,25分到手的感觉真的挺爽的。

#include<iostream>
#include<vector>
using namespace std;
int N, M;
bool visited[1001] = { 0 };
vector<int>v[1001];
vector<int>ans;
int num = 0;
int main() {
	cin >> N >> M;
	while (M--) {
		int a, b;
		cin >> a >> b;
		v[a].push_back(b);
		v[b].push_back(a);
	}
	for (int i = 1; i <= N; i++) {
		if (visited[i])continue;
		else visited[i] = 1;
		ans.push_back(i);
		for (int j : v[i])visited[j] = 1;
	}
	for (int i = 0; i < ans.size(); i++) {
		if (i)cout << ' ';
		cout << ans[i];
	}
}

A-4 The Smallest Open Interval

Given a set S of points on the x-axis. For any point p, you are suppose to find the smallest open interval that contains p, provided that the two ends of the interval must be in S.

Input Specification:

Each input file contains one test case. Each case consists of several lines of commands, where each command is given in the format:

cmd num

where cmd is either I for “insert”, or Q for “query”, or E for “end”; and num is an integer coordinate of a point on the x-axis. It is guaranteed that num is in the range [−109,109].
The input is ended by E. It is guaranteed that there are no more than 105 distinct points in S, and so is the number of queries. The total number of commands (E not included) is no more than 3×105.

Output Specification:

For each I case, insert num into S. For each Q case, output the smallest open interval that contains num in the format (s1, s2), where both s1 and s2 must be in S. On the other hand, if num is no larger than the smallest point in S, s1 shall be replaced by -inf, representing negative infinity; or if num is no smaller than the largest point in S, s2 shall be replaced by +inf, representing positive infinity.
It is guaranteed that there must be at least 1 point in S before the first query.

input:
I 100
Q 100
I 0
I 33
I -200
Q 25
Q 33
Q -200
Q 200
E
output:
(-inf, +inf)
(0, 33)
(0, 100)
(-inf, 0)
(100, +inf)

题意:在一个开放数轴上找一个点的左右边界。可以有插入、查询和结束三种操作。

思路:数轴用set来存,因为set可以自动排序,并且可以找到查找的数字的位置,通过++和–操作可以轻松找到左右边界。当然开始前将正无穷和负无穷先插入到set中。注意set的迭代器是有++和–的操作的,考试过程中对这个点不太熟,从头到尾进行遍历,导致后面13分超时了。下面这是考试后优化的版本,题目集提交后AC了。

#include<iostream>
#include<set>
using namespace std;
set<int>s;
const int INF = 0x3f3f3f3f;
const int Left = -INF, Right = INF;
int main() {
	char oper;
	s.insert(Left);
	s.insert(Right);
	while ((oper = getchar()) != 'E') {
		int i;
		getchar();
		scanf("%d", &i);
		getchar();
		if (oper == 'I') {
			s.insert(i);
			continue;
		}
		if (oper == 'Q') {
			bool flag = 1;
			if (!s.insert(i).second)flag = 0;
			set<int>::iterator it = s.find(i);
			int l, r;
			it++;
			r = *it--;//右边界
			it--;
			l = *it;//左边界
			cout << '(';
			if (l == Left)cout << "-inf, ";
			else cout << l << ", ";
			if (r == Right)cout << "+inf)\n";
			else cout << r << ")\n";
			if (flag)s.erase(i);
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值