PAT-2022年春季考试-甲级,题解
仅提供个人思路~
题目链接:购买考试券 - PAT(甲级)2022年春仿真卷 (pintia.cn)
7-1 Simple Lie Detection (20 分)
/* n道题,阈值为t(分数超过t要输出!!!) ,k个作答 判题规则: 1.字符串首字母为f,分数-2 2.字符串尾字母为a,分数-1 3.每个相同相同字母的len>5的最长答案段,分数+3 即aaaaaaabbbbbbccccccc,分数为9 4.字母a后为e或者h,分数-4 5.连续递增字母且len>3,分数+5 */ #include<bits/stdc++.h> using namespace std; int main() { int n,t,k; cin>>n>>t>>k; while(k--) { int res=0; string s; cin>>s; if(s[0]=='f')res-=2; if(s[n-1]=='a')res-=1; //for every longest segment of answeres where the same letter is chosen for consecutive questions, //if the segment length is larger than 5, the score is to +3; //记录每个字母的最长连续段 int longest_len[200]={0}; for(int i=0;i<n;) { int tmp_len=0; if(i+5<n&&s[i]==s[i+1]&&s[i]==s[i+2]&&s[i]==s[i+3]&&s[i]==s[i+4]&&s[i]==s[i+5]) { i+=5; tmp_len+=5; while(s[i]==s[i+1]&&i+1<n)i++,tmp_len++; } else i++; if(tmp_len>longest_len[s[i-1]])longest_len[s[i-1]]=tmp_len; } //验证字母的连续段是否与longest_len相符,是则+5 for(int i=0;i<n;) { int tmp_len=0; if(i+5<n&&s[i]==s[i+1]&&s[i]==s[i+2]&&s[i]==s[i+3]&&s[i]==s[i+4]&&s[i]==s[i+5]) { i+=5; tmp_len+=5; while(s[i]==s[i+1]&&i+1<n)i++,tmp_len++; } else i++; if(tmp_len==longest_len[s[i-1]]&&tmp_len)res+=3; } //注意every,测试点1和4会卡 for(int i=0;i+1<n;) { if(s[i]=='a'&&s[i+1]=='e'||s[i]=='a'&&s[i+1]=='h') { res-=4; i+=2; } else i++; } for(int i=0;i<n;) { if(i+3<n&&s[i+1]==s[i]+1&&s[i+2]==s[i]+2&&s[i+3]==s[i]+3) { res+=5; i+=3; while(s[i+1]==s[i]+1&&i+1<n)i++; } else i++; } if(res>t) cout<<res<<"!!!"<<endl; else cout<<res<<endl; } return 0; }
7-2 The First K Largest Numbers (25 分)
#include<bits/stdc++.h> using namespace std; //存1e6会内存超限 int a[100]; bool cmp(int n1,int n2) { return n1>n2; } int main() { int n,k; //cin会超时 scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) { //只存前k+1个数并进行排序,很经典的面试题~ //优先队列、multiSet、map等都可以过这题,try a try int tmp=min(i,k+1); scanf("%d",&a[tmp]); sort(a+1,a+tmp+1,cmp); } for(int i=1;i<=k&&i<=n;i++) { if(i==1)printf("%d",a[i]); else printf(" %d",a[i]); } printf("\n"); return 0; }
7-3 Is It A Binary Search Tree - Again (25 分)
#include<bits/stdc++.h> using namespace std; int n,t[2050]; int a[2050],len=1; //二叉搜索树的中序变历为升序 void inOrder(int cur) { if(t[cur]==-1||cur>n)return; inOrder(cur*2); a[len++]=t[cur]; inOrder(cur*2+1); } int main() { cin>>n; for(int i=1;i<=n;i++)cin>>t[i]; inOrder(1); int b[2050]={0}; for(int i=1;i<len;i++)b[i]=a[i]; sort(b+1,b+len); //用b(排序后的a)判断a是否为升序 bool flag=0; for(int i=1;i<len;i++) { if(b[i]!=a[i])flag=1; } if(!flag)cout<<"YES"<<endl; else cout<<"NO"<<endl; for(int i=1;i<len;i++) { if(i==1)cout<<a[i]; else cout<<" "<<a[i]; } cout<<endl; return 0; }
7-4 The Rescue (30 分)
/* 0 ↑ 3← →1 ↓ 2 ?为人所在位置 有三个距离最远(4)位置,pick了代码最small的,给了他0011指令 ?#??? ??X?? ??##? ???#? 起初图中所有0点都可能有人,所有人执行指令0011后(撞墙不走、到X不走),可能在四个?点处 ?#OO? OOXO? OO##O OO?#O pick了距离最远(4)的最下面一排的问号,给了他3001指令...... ans的本质是:所以遍布在各个位置的人,听到这些指令后一一执行,或早或晚最后都能到X这个位置 */ #include<bits/stdc++.h> using namespace std; const int INF=0x3f3f3f; char p[105][105]; int len[105][105],vis[105][105]; typedef pair<int, int> PII; map<PII,int> is_hiker; struct node { int x,y; //{x,y}到X的路 string path; }; //先搜出x到所有0的距离 void bfs(int x,int y) { memset(vis,0,sizeof vis); queue<PII>q; q.push({x,y}); vis[x][y]=1; while(!q.empty()) { PII cur=q.front(); q.pop(); for(int i=0;i<4;i++) { int tx=cur.first,ty=cur.second; if(i==0)tx--; if(i==1)ty++; if(i==2)tx++; if(i==3)ty--; if(!vis[tx][ty]&&is_hiker[{tx,ty}]) { vis[tx][ty]=1; len[tx][ty]=len[cur.first][cur.second]+1; q.push({tx,ty}); } } } } //求出{x,y}到x的最small的路,反之求不出来 string cal_path(int x,int y) { memset(vis,0,sizeof vis); queue<struct node> q; struct node start={x,y,""}; q.push(start); vis[x][y]=1; while(true) { struct node cur=q.front(); q.pop(); for(int i=0;i<4;i++) { int tx=cur.x,ty=cur.y; if(i==0)tx--; if(i==1)ty++; if(i==2)tx++; if(i==3)ty--; if(!vis[tx][ty]&&p[tx][ty]!='#') { vis[tx][ty]=1; char ch='0'+i; if(p[tx][ty]=='X')return cur.path+ch; struct node nex={tx,ty,cur.path+ch}; q.push(nex); } } } } //模拟从{tx,ty}按照s指令会走到哪个位置 pair<int, int> walk(int tx,int ty,string s) { for(int i=0;i<s.size();i++) { //遇墙不走 if(s[i]=='0'&&p[tx-1][ty]!='#')tx--; if(s[i]=='1'&&p[tx][ty+1]!='#')ty++; if(s[i]=='2'&&p[tx+1][ty]!='#')tx++; if(s[i]=='3'&&p[tx][ty-1]!='#')ty--; //终点不走 if(p[tx][ty]=='X')return {tx,ty}; } return {tx,ty}; } int main() { int n,m; cin>>n>>m; //把边围起来 int x,y; queue<PII> hiker_place; for(int i=0;i<=m+1;i++)p[0][i]='#',p[n+1][i]='#',len[0][i]=len[n+1][i]=INF; for(int i=0;i<=n+1;i++)p[i][0]='#',p[i][m+1]='#',len[i][0]=len[i][m+1]=INF; for(int i=1;i<=n;i++) { getchar(); for(int j=1;j<=m;j++) { cin>>p[i][j]; if(p[i][j]=='X')x=i,y=j; if(p[i][j]=='#')len[i][j]=INF; //hiker_place是人可能在的地方的队列集合,is_hiker是判断该点是否可能有人 if(p[i][j]=='O')hiker_place.push({i,j}),is_hiker[{i,j}]=1; } } //找X到O的最远距离 bfs(x,y); string ans=""; while(!hiker_place.empty()) { int max_len=0; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if(len[i][j]==INF)continue; else if(is_hiker[{i,j}]&&len[i][j]>max_len)max_len=len[i][j]; } } string tmp=""; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if(is_hiker[{i,j}]&&len[i][j]==max_len) { string path=cal_path(i,j); if(tmp==""||path<tmp)tmp=path; } } } ans+=tmp; //清空人的位置,将该步所有人的可能位置按照tmp指令进行模拟,得到新的所有人的可能位置,赋值给queue及map is_hiker.clear(); queue<pair<int, int> > tmp_place; while(!hiker_place.empty()) { pair<int, int> cur=hiker_place.front(),nex; hiker_place.pop(); nex=walk(cur.first,cur.second,tmp); if(!is_hiker[nex]&&p[nex.first][nex.second]!='X') { is_hiker[nex]=1; tmp_place.push(nex); } } hiker_place=tmp_place; } cout<<ans<<endl; return 0; }