【PTA】PAT(甲级)2022年冬季考试自测

个人学习记录,代码难免不尽人意。

这次考试,e,第一题我看好多人都没理解题意做错了,还有第四题真的是比较意外,之前做的题都是给序列建树,但是这次让判断是否可以生成树,之前从来没有遇到过这类题,所以第四题要好好记住。第二题和第三题到是很简单。

A-1 Reduction of Proper Fractions
A Proper Fraction(真分数)is a fraction where the numerator(分子)is less than the denominator(分母). To reduce a fraction, we are supposed to cross out any common factors between the numerator and the denominator.

Here is another way to do the reduction: simply cross out any common digits. In most of the cases, this way cannot give the correct result. However, sometimes it happends to work! For example: 26/65 = 2/5 where 6 is crossed out.

Now given a proper fraction, you are supposed to tell if this simple reduction works or not.

Input Specification:
Each input file contains one test case, with the numerator a and the denominator b of the proper fraction given in a line, separated by a space. It is guaranteed that 0

Output Specification:
For each test case, print in a line both fractions before and after the simple reduction. If they are equal, put a = between them; else put != instead. The format is either a/b = c/d or a/b != c/d.

Sample Input 1:
39 195
Sample Output 1:
39/195 = 3/15
Sample Input 2:
1234 2345
Sample Output 2:
1234/2345 != 1/5
Sample Input 3:
1234 5678
Sample Output 3:
1234/5678 = 1234/5678

#include
#include
#include

using namespace std;
int table1[10]={0};
int table2[10]={0};
int temp1[10]={0};
int temp2[10]={0};
int toint(string s){
	int n=0;
	for(int i=0;i<s.size();i++){
		n=n*10+s[i]-'0';
	}
	return n;
}
int gcd(int a,int b){
	if(b==0) return a;
	else return gcd(b,a%b);
}
int main(){
	string a,b;
	cin >> a >> b;
	for(int i=0;i<a.size();i++){
			table1[a[i]-'0']++;
	}

	for(int i=0;i<b.size();i++){
		table2[b[i]-'0']++;
}
for(int i=0;i<10;i++){
	temp1[i]=table1[i];
	temp2[i]=table2[i];
}
	string a1,b1;
	for(int i=0;i<a.size();i++){
		if(table1[a[i]-'0']==0||table2[a[i]-'0']==0){
			a1=a1+a[i];
		}
		else{
			table1[a[i]-'0']--;
			table2[a[i]-'0']--;
		}
	}
	for(int i=0;i<b.size();i++){
		if(temp1[b[i]-'0']==0||temp2[b[i]-'0']==0){
			b1=b1+b[i];
		}
		else{
			temp1[b[i]-'0']--;
			temp2[b[i]-'0']--;
		}
	}
	int num1=toint(a);
	int num2=toint(b);
	int factor;
    factor=gcd(num2,num1);
	num1=num1/factor;
	num2=num2/factor;
	int temp1=toint(a1);
	int temp2=toint(b1);
	if(temp1==temp2&temp1==0){
		cout <<a<<"/"<<b<<" != 0/0";
		return 0;
	}
	int factor1;
	if(temp1>temp2)
	factor1=gcd(temp1,temp2);
	else factor1=gcd(temp2,temp1);
	temp1=temp1/factor1;
	temp2=temp2/factor1;
	if(num1==temp1&&num2==temp2){
		cout << a<<"/"<<b<<" = "<<toint(a1)<<"/"<<toint(b1);
	}
	else cout << a<<"/"<<b<<" != "<<toint(a1)<<"/"<<toint(b1);
} 

题目的意思是“对于A和B中的每一个相同的字符都去除,而不是说存在相同的都要去除”。(我感觉出题人就喜欢不把话说明白让你猜哈哈),举个例子

a=1112,b=1234,正确答案c=112,d=34
明白了这个,这道题就是送分题了。

A-2 Luggage Pickup
【PTA】PAT(甲级)2022年冬季考试自测_第1张图片
When a flight arrives, the passengers will go to the Arrivals area to pick up their baggage from a luggage conveyor belt (行李传送带).

Now assume that we have a special airport that has only one pickup window for each conveyor belt. The passengers are asked to line up to pick up their luggage one by one at the window. But if one arrives at the window yet finds out that one is not the owner of that luggage, one will have to move to the end of the queue and wait for the next turn. At the mean time, the luggage at the window will wait until its owner picks it up. Suppose that each turn takes 1 minute, your job is to calculate the total time taken to clear the conveyor belt, and the average waiting time for the passengers.

For example, assume that luggage i belongs to passenger i. If the luggage come in order 1, 2, 3, and the passengers come in order 2, 1, 3. Luggage 1 will wait for 2 minutes to be picked up by passenger 1. Then the luggage queue contains 2 and 3, and the passenger queue contains 3 and 2. So luggage 2 will wait for 2 minutes to be picked up by passenger 2. And finally 3 is done at the 5th minute. The average waiting time for the passengers is (2+4+5)/3≈3.7.

Input Specification:
Each input file contains one test case. The first line gives a positive integer N (≤10 3 ). Then N numbers are given in the next line, which is a permutation of the integers in [1,N], representing the passenger queue. Here we are assuming that the luggage queue is in order of 1, 2, …, N, and the i-th luggage belongs to passenger i.

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 conveyor belt, and the average waiting time for the passengers (output 1 decimal place). The numbers must be separated by 1 space, and there must be no extra space at the beginning or the end of the line.

Sample Input:
5
3 5 1 2 4
Sample Output:
9 6.0

#include
#include
#include
#include
using namespace std;
const int maxn=1010;
queue<int> luggage,people;
int minutes[maxn];
int main(){
	int n;
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		int num;
		scanf("%d",&num);
		people.push(num);
	}
	for(int i=1;i<=n;i++){
		luggage.push(i);
	}
	int cnt=0;
	
	while(!luggage.empty()&&!people.empty()){
		int now=luggage.front();
		int temp=people.front();
		if(now==temp){
			cnt++;
			minutes[now]=cnt;
			luggage.pop();
			people.pop(); 
		}
		else{
			cnt++;
			people.pop();
			people.push(temp);
		}
	}
	cout << cnt<<" ";
	int sum=0;
	for(int i=1;i<=n;i++){
		sum+=minutes[i];
	}
	double res=(1.0*sum)/(1.0*n);
	printf("%.1lf",res);
} 

这道题就是很简单的模拟题,不多说了
【PTA】PAT(甲级)2022年冬季考试自测_第2张图片In graph theory, given a connected graph G, the vertices whose removal would disconnect G are known as articulation points. For example, vertices 1, 3, 5, and 7 are the articulation points in the graph shown by the above figure (also given by the sample input).

It is a bit complicated to find the articulation points. Here you are only asked to check if a given vertex is an articulation point or not.

Input Specification:
Each input file contains one test case. For each case, the first line contains 3 positive integers: N (≤10
3
), M (≤10
4
), and K (≤100), which are the number of vertices, the number of edges, and the number of queries, respectively. Then M lines follow, each gives an undirected edge in the format:

v1 v2
where v1 and v2 are the two ends of an edge. Here we assume that all the vertices are numbered from 0 to N−1. It is guaranteed that v1 is never the same as v2, and the graph is connected.

Finally a line of queries are given, which contains K vertices to be checked. The numbers in a line are separated by spaces.

Output Specification:
Output a string of 0’s and 1’s in a line. That is, for each query, print 1 if the given vertex is an articulation point, or 0 if not. There must be no space between the answers.

Sample Input:
10 11 8
0 1
8 7
9 7
1 2
1 3
3 5
5 7
2 4
3 4
5 6
6 7
5 2 9 1 6 3 2 7
Sample Output:
10010101

#include
#include
#include
#include
using namespace std;
const int maxn=1010;
const int INF=1000000000;
int G[maxn][maxn],temp[maxn][maxn];
bool visit[maxn]={false};
void dfs(int begin,int n){
	for(int i=0;i<n;i++){
		if(!visit[i]&&temp[begin][i]!=INF){
			visit[i]=true;
			dfs(i,n);
		}
	}
}
bool dfstravel(int n){

	int num=0;
	for(int i=0;i<n;i++){
		if(!visit[i]){
			visit[i]=true;
			num++;
			dfs(i,n);
		}
	}

	if(num>1) return false;
	else return true;
}
int main(){
	for(int i=0;i<maxn;i++){
		for(int j=0;j<maxn;j++){
			G[i][j]=INF;
		}
	}
      int n,m,k;
	  scanf("%d %d %d",&n,&m,&k);
	  for(int i=0;i<m;i++){
	  	int a,b;
	  	scanf("%d %d",&a,&b);
	  	G[a][b]=1;
	  	G[b][a]=1;
	  }
	for(int p=0;p<k;p++){
		int num;
		scanf("%d",&num);
		for(int i=0;i<maxn;i++){
		for(int j=0;j<maxn;j++){
			temp[i][j]=G[i][j];
		}
	}
		for(int i=0;i<n;i++){
				temp[num][i]=INF;
				temp[i][num]=INF;
		}
		fill(visit,visit+maxn,false);
		visit[num]=true;//删去节点赋为true防止再处理 
		if(dfstravel(n)){
			printf("0");
		}
		else printf("1");
	}  	
} 

这道题也很简单,不多说了。

A-4 Check Inorder Traversals
Suppose that all the keys in a binary tree are distinct positive integers. A unique binary tree can be determined by a given pair of postorder and inorder traversal sequences, or preorder and inorder traversal sequences. However, if only the postorder and preorder traversal sequences are given, the corresponding tree may no longer be unique.

Now given a pair of postorder and preorder traversal sequences, you are supposed to check a set of inorder traversal sequences, and answer whether or not they are indeed inorder traversal sequences of the tree.

Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N (≤ 30), the total number of nodes in the binary tree. The second line gives the preorder sequence and the third line gives the postorder sequence.

Then another positive integer K (≤ 10) is given, followed by K lines of inorder traversal sequences.

Each sequence consists of N positive integers. All the numbers in a line are separated by a space.

Output Specification:
For each inorder traversal sequence, print in a line Yes if it is an inorder traversal sequence of the tree, or No if not.

On the other hand, there is another possible case that the given pre- and postorder traversal sequences can NOT form any tree at all. In that case, first print in a line Are you kidding me?. Then for each inorder traversal sequence of the input, try to construct a tree with the given preorder traversal sequence, and output in a line the correct postorder traversal sequence. If it is still impossible, output You must be kidding me! instead.

Sample Input 1:
4
1 2 3 4
2 4 3 1
4
2 1 3 4
1 2 3 4
2 1 4 3
2 1 5 6
Sample Output 1:
Yes
No
Yes
No
Sample Input 2:
7
1 2 3 4 6 7 5
6 7 5 4 3 2 1
3
2 1 6 4 7 3 5
2 1 6 7 4 3 5
2 3 1 7 4 5 6
Sample Output 2:
Are you kidding me?
2 6 7 4 5 3 1
2 7 6 4 5 3 1
You must be kidding me!

#include
#include
using namespace std;
const int maxn=35;
int pre[maxn];
int post[maxn];
int in[maxn];
struct node{
	int data;
	node* lchild;
	node* rchild;
};
node* newnode(int data){
	node* root=new node;
	root->data=data;
	root->lchild=NULL;
	root->rchild=NULL;
	return root; 
}


bool flag=true;
void build(int prel,int prer,int postl,int postr){
	if(prel>=prer||postl>=postr) return;
	if(pre[prel]!=post[postr]){
		flag=false;
		return;
	}
	int index=-1;
	for(int i=postl;i<=postr;i++){
		if(post[i]==pre[prel+1]){
			index=i;
			break;
		}
	}
	if(index==-1){
		flag=false;
		return;
	}
	int leftnum=index-postl+1;
	build(prel+1,prel+leftnum,postl,index);
	build(prel+leftnum+1,prer,index+1,postr-1);
}
bool flag1=true;
node* create(int prel,int prer,int inl,int inr){
	if(prel>prer) return NULL;
	int mid=pre[prel];
	int index=-1;
	for(int i=inl;i<=inr;i++){
		if(in[i]==mid){
			index=i;
			break;
		}
	}
	if(index==-1){
		flag1=false;
		return NULL;
	}
	int leftnum=index-inl;
	node* root=newnode(mid);
	root->lchild=create(prel+1,prel+leftnum,inl,index-1);
	root->rchild=create(prel+1+leftnum,prer,index+1,inr);
	return root;
}
int temp[maxn];
int cnt=0;
void dfs(node* root){
	if(root==NULL) return ;
	dfs(root->lchild);
	dfs(root->rchild);
	temp[cnt++]=root->data;
}
int main(){
     int n;
	 scanf("%d",&n);
	 for(int i=0;i<n;i++){
	 	scanf("%d",&pre[i]);
	 }	
	 for(int i=0;i<n;i++){
	 	scanf("%d",&post[i]);
	 }
	 build(0,n-1,0,n-1);
	 
	 if(flag){
        int k;
        scanf("%d",&k);
        for(int i=0;i<k;i++){
        	for(int j=0;j<n;j++) scanf("%d",&in[j]);
        	flag1=true;
        	node* root=create(0,n-1,0,n-1);
        	if(!flag1){
        		printf("No\n");
			}
			else{
				cnt=0;
				dfs(root);
				int m=0;
				for(;m<n;m++){
					if(post[m]!=temp[m]){
						break;
					}
				}
				if(m!=n){
					printf("No\n");
				}
				else printf("Yes\n");
			}
		}
		
	 }
	 else{
	 	int k;
        scanf("%d",&k);
		printf("Are you kidding me?\n");
        for(int i=0;i<k;i++){
            for(int j=0;j<n;j++) scanf("%d",&in[j]);
            flag1=true;
		    node* root=create(0,n-1,0,n-1);
		    if(!flag1){
		    	printf("You must be kidding me!\n");
			}
			else{
				cnt=0;
				dfs(root);
				for(int j=0;j<n;j++){
					printf("%d",temp[j]);
					if(j!=n-1)printf(" ");
					else printf("\n");
				}
			}
		}
	 }
}

这道题需要熟练掌握!一开始我想的有点复杂了,其实判断前序序列和后序序列能不能生成一个二叉树只需要判断pre的第一个和post的最后一个是否相等即可!除此之外,题目还有一个坑点是两个序列不一定是完全覆盖的,需要判断!

各位肯定对用前序序列和中序序列建树的过程和方法烂熟于心了!那么我们就可以用模板来举一反三求解此题。我们可以用同样的方法来处理左右子树,如果各自序列对应的根节点不相等就返回false,除此之外,因题目的特殊要求,如果在第二个序列查找不到对应的数字,就要返回false。

你可能感兴趣的:(PTA,c++,算法,pat)