PAT甲级刷题日记(一)
日更(逃
1099 Build A Binary Search Tree
Mon Jun 6 2022
Link
30分
思路:对key按从小到大排序,然后中序遍历树将key值放进去(二叉搜索树通过中序遍历可得到顺序序列),最后层次遍历输出。
中序遍历的DFS和层次遍历的BFS都使用了非递归写法。
AC代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <string> #include <string.h> #include <vector> #include <stack> #include <queue> using namespace std; #define N 100 int n,cnt; int lch[N],rch[N],key[N],ans[N]; int DFS(int x){ stack<int>st; while(x!=-1||!st.empty()){ if(x!=-1){ st.push(x); x=lch[x]; }else{ x=st.top(); st.pop(); ans[x]=key[cnt++]; x=rch[x]; } } } void levelTraverse(int x){ queue<int>q; printf("%d",ans[x]); if(lch[x]!=-1) q.push(lch[x]); if(rch[x]!=-1) q.push(rch[x]); while(!q.empty()){ x=q.front(); q.pop(); printf(" %d",ans[x]); if(lch[x]!=-1) q.push(lch[x]); if(rch[x]!=-1) q.push(rch[x]); } printf("\n"); } int main(){ scanf("%d",&n); for(int i=0;i<n;++i) scanf("%d%d",&lch[i],&rch[i]); for(int i=0;i<n;++i) scanf("%d",&key[i]); sort(key,key+n); DFS(0); levelTraverse(0); return 0; }
1102 Invert a Binary Tree
Mon Jun 6 2022
Link
25分
题目很简单,主要是发现了scanf的坑:
输入:- -
如果写成scanf("%c%c",&ch1,&ch2)
就会把空格读进去,所以最好用cin>>ch1>>ch2
。
AC代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <string> #include <string.h> #include <vector> #include <stack> #include <queue> using namespace std; #define N 15 int n; int lch[N],rch[N],fa[N]; void levelOrder(int x){ queue<int>q; cout<<x; if(lch[x]!=-1) q.push(lch[x]); if(rch[x]!=-1) q.push(rch[x]); while(!q.empty()){ x=q.front(); q.pop(); cout<<" "<<x; if(lch[x]!=-1) q.push(lch[x]); if(rch[x]!=-1) q.push(rch[x]); } cout<<endl; } void inOrder(int x){ stack<int>st; bool flag=true; while(x!=-1||!st.empty()){ if(x!=-1){ st.push(x); x=lch[x]; }else{ x=st.top(); st.pop(); if(flag){cout<<x;flag=false;} else cout<<" "<<x; x=rch[x]; } } cout<<endl; } int main(){ cin>>n; memset(fa,-1,sizeof(fa)); for(int i=0;i<n;++i){ char l,r; cin>>l>>r; if(l=='-') rch[i]=-1; else{ rch[i]=(int)(l-'0'); fa[rch[i]]=i; } if(r=='-') lch[i]=-1; else{ lch[i]=(int)(r-'0'); fa[lch[i]]=i; } } int root=0; for(int i=0;i<n;++i) if(fa[i]==-1){ root=i; break; } levelOrder(root); inOrder(root); return 0; }
看了柳神的代码,给我提供了一种层次遍历的新思路——可以通过对节点所在层数和同一层的节点编号进行排序得到:
struct node { int id, l, r, index, level; } a[100]; vector<node> v1; void dfs(int root, int index, int level) { if (a[root].r != -1) dfs(a[root].r, index * 2 + 2, level + 1); v1.push_back({root, 0, 0, index, level}); if (a[root].l != -1) dfs(a[root].l, index * 2 + 1, level + 1); } bool cmp(node a, node b) { if (a.level != b.level) return a.level < b.level; return a.index > b.index; } int main() { //... dfs(root, 0, 0); vector<node> v2(v1); sort(v2.begin(), v2.end(), cmp); //... return 0; }
1028 List Sorting
Mon Jun 6 22:57
Link
25分
从这篇开始就精确到时刻了……毕竟无聊嘛。
都晚上了,就做简单题好了ε=ε=ε=ε=ε=ε=┌(; ̄◇ ̄)┘
注意⚠️:strcmp
有坑。后来改成string
就全过了,不然只能过部分测试用例。
strcmp
的比较规则是:将两个字符串自左至右逐个字符相比(按ASCII码值大小比较),直到出现不同的字符或遇到’\0’为止。
可能原因:src
如果C字符串s1和s2相等但都没有\0
,那么它们的比较缺少终止条件,因此strcmp
返回的结果不正确。
这个\0
非常重要,可以用下面三段代码自行测试:(控制台输入12345)
#include<stdio.h> #include<string.h> int main() { char s1[5]; char s2[5] = {'1','2','3','4','5'}; for (int i = 0; i < 5; i++) scanf("%c", &s1[i]); int result = strcmp(s1, s2); printf("%d",result); }
#include<stdio.h> #include<string.h> int main() { char s1[6]={'\0'}; char s2[6] = {'1','2','3','4','5'}; for (int i = 0; i < 5; i++) scanf("%c", &s1[i]); int result = strcmp(s1, s2); printf("%d",result); }
#include<stdio.h> #include<string.h> int main() { char s1[6]={'\0'}; char s2[5] = {'1','2','3','4','5'}; for (int i = 0; i < 5; i++) scanf("%c", &s1[i]); int result = strcmp(s1, s2); printf("%d",result); }
不多说了,回到正题。
AC代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <string> #include <string.h> #include <vector> #include <stack> #include <queue> using namespace std; int n,c; struct node{ int id; string name; int grade; }stu[1000010]; bool cmp1(const node&a,const node&b){ return a.id<b.id; } bool cmp2(const node&a,const node&b){ // if(strcmp(a.name,b.name)!=0) return strcmp(a.name,b.name)<0; if(a.name!=b.name) return a.name<b.name; return a.id<b.id; } bool cmp3(const node&a,const node&b){ if(a.grade!=b.grade) return a.grade<b.grade; return a.id<b.id; } int main(){ scanf("%d%d",&n,&c); for(int i=1;i<=n;++i) cin>>stu[i].id>>stu[i].name>>stu[i].grade; if(c==1) sort(stu+1,stu+1+n,cmp1); else if(c==2) sort(stu+1,stu+1+n,cmp2); else sort(stu+1,stu+1+n,cmp3); for(int i=1;i<=n;++i) printf("%06d %s %d\n",stu[i].id,stu[i].name.c_str(),stu[i].grade); return 0; }
1016 Phone Bills
Tue Jun 7 20:52
Link
25分
万恶的模拟题,对我这种总是看不懂题/存在理解偏差/看漏条件的人极不友好。
还有亿点点细节需要注意。
坑点合集:
- 按照时间排序后,两个可以匹配的记录中第一个一定是online,第二个是offline
- toll的单位是“美分/分钟”,而且注意每个toll代表的区间是什么。最好从0开始存储。
- 话费的计算:我的方法是,先计算天数差需要的钱,然后分别减去左端点和加上右端点(看代码应该秒懂)
看到有的博客说最后算出的money为0就不能输出?这里表示质疑。题目都说了相同顾客的记录是不会出现相同时间的,那么只要能够匹配就不会出现money为0的情况。如果全都不能匹配才不会输出。
个人认为最大的坑就是第一个(其实我还没读懂那个意思)
Each on-line record is paired with the chronologically next record for the same customer provided it is an off-line record. Any on-line records that are not paired with an off-line record are ignored, as are off-line records not paired with an on-line record.
代码极其复杂,写得真心不好。好多地方可以改进。
AC代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <string> #include <string.h> #include <vector> #include <unordered_map> using namespace std; #define N 1010 int n,month,sum; int toll[24]; struct node{ string name; int day,hour,minute; int online=0; bool operator<(const node&x)const{ if(day!=x.day) return day<x.day; if(hour!=x.hour) return hour<x.hour; return minute<x.minute; } }; unordered_map<string,int>mp; vector<node>v[N],vl[N]; struct node1{ string name; int index; bool operator<(const node1&x)const{return name<x.name;} }; vector<node1>vp; struct node2{ int day[2],hour[2],minute[2]; int len; double money; }; int main(){ for(int i=0;i<24;++i){ cin>>toll[i]; sum+=60*toll[i]; } cin>>n; int cnt=0; for(int i=1;i<=n;++i){ string s; node tmp; cin>>tmp.name; if(!mp.count(tmp.name)) mp[tmp.name]=cnt++; scanf("%d:%d:%d:%d",&month,&tmp.day,&tmp.hour,&tmp.minute); cin>>s; if(s[1]=='n') tmp.online=1; v[mp[tmp.name]].push_back(tmp); } unordered_map<string,int>::iterator it=mp.begin(); for(;it!=mp.end();++it){ node1 tmp; tmp.name=it->first,tmp.index=it->second; vp.push_back(tmp); } sort(vp.begin(),vp.end()); for(int i=0;i<vp.size();++i) vl[i]=v[vp[i].index]; for(int i=0;i<cnt;++i){ sort(vl[i].begin(),vl[i].end()); vector<node2>cur; int j1=0,j2=1; while(j1<vl[i].size()&&j2<vl[i].size()){ if(!vl[i][j1].online){j1++,j2++;continue;} if(vl[i][j1].online^vl[i][j2].online){ node2 tmp; tmp.day[0]=vl[i][j1].day,tmp.day[1]=vl[i][j2].day; tmp.hour[0]=vl[i][j1].hour,tmp.hour[1]=vl[i][j2].hour; tmp.minute[0]=vl[i][j1].minute,tmp.minute[1]=vl[i][j2].minute; tmp.len=(vl[i][j2].day*24*60+vl[i][j2].hour*60+vl[i][j2].minute)-(vl[i][j1].day*24*60+vl[i][j1].hour*60+vl[i][j1].minute); tmp.money=(tmp.day[1]-tmp.day[0])*sum; for(int k=tmp.hour[0]-1;k>=0;--k) tmp.money-=toll[k]*60; for(int k=0;k<=tmp.hour[1]-1;++k) tmp.money+=toll[k]*60; tmp.money-=tmp.minute[0]*toll[tmp.hour[0]]; tmp.money+=tmp.minute[1]*toll[tmp.hour[1]]; tmp.money/=100; cur.push_back(tmp); j1+=2,j2+=2; }else j1++,j2++; } if(cur.size()){ cout<<vl[i][0].name; printf(" %02d\n",month); double tot=0; for(int k=0;k<cur.size();++k){ printf("%02d:%02d:%02d %02d:%02d:%02d %d $%.2lf\n",cur[k].day[0],cur[k].hour[0],cur[k].minute[0],cur[k].day[1],cur[k].hour[1],cur[k].minute[1],cur[k].len,cur[k].money); tot+=cur[k].money; } printf("Total amount: $%.2lf\n",tot); } } return 0; }
1017 Queueing at Bank
Wed Jun 8 09:03
Link
25分
可以用优先队列,也可以不用。
注意,对于每个顾客,是取当前k个窗口中最早空闲的那个,而不是每次把k个窗口排序再依次安排顾客。这是因为,假设i窗口先空闲,紧接着是j窗口空闲,那么第cur个顾客去了i窗口,但是第cur+1个顾客可能不是去j窗口,而是去i窗口,因为i窗口仍然可能会比j窗口更早空闲。
AC代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <string> #include <string.h> #include <vector> using namespace std; int n,k,start,_end,cnt; double ans; vector<int>wind; struct node{ int st,p; bool operator<(const node&x)const{return st<x.st;} }cu[10010]; int main(){ scanf("%d%d",&n,&k); start=8*3600,_end=17*3600; for(int i=1;i<=n;++i){ int h,m,s,p; scanf("%d:%d:%d %d",&h,&m,&s,&p); if(h*3600+m*60+s>_end) continue; cu[++cnt].st=h*3600+m*60+s; cu[cnt].p=min(p,60)*60; } sort(cu+1,cu+1+cnt); for(int i=1;i<=k;++i) wind.push_back(start); for(int i=1;i<=cnt;++i){ vector<int>::iterator it=min_element(wind.begin(),wind.end()); int pos=distance(wind.begin(),it),minv=*it; if(minv<=cu[i].st) wind[pos]=cu[i].st+cu[i].p; else{ ans+=minv-cu[i].st; wind[pos]=minv+cu[i].p; } } ans=ans/(60.0*cnt); printf("%.1lf\n",ans); return 0; }
把优先队列做法也放上来:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <string> #include <string.h> #include <vector> #include <queue> using namespace std; int n,k,start,_end,cnt; double ans; priority_queue<int,vector<int>,greater<int>>q; //小根堆 struct node{ int st,p; bool operator<(const node&x)const{return st<x.st;} }cu[10010]; int main(){ scanf("%d%d",&n,&k); start=8*3600,_end=17*3600; for(int i=1;i<=n;++i){ int h,m,s,p; scanf("%d:%d:%d %d",&h,&m,&s,&p); if(h*3600+m*60+s>_end) continue; cu[++cnt].st=h*3600+m*60+s; cu[cnt].p=min(p,60)*60; } sort(cu+1,cu+1+cnt); for(int i=1;i<=k;++i) q.push(start); for(int i=1;i<=cnt;++i){ int top=q.top(); q.pop(); if(top<=cu[i].st) q.push(cu[i].st+cu[i].p); else{ ans+=top-cu[i].st; q.push(top+cu[i].p); } } ans=ans/(60.0*cnt); printf("%.1lf\n",ans); return 0; }
1019 General Palindromic Number
Wed Jun 8 10:30
Link
20分
第一遍只过了部分测试用例,做法是先打表,算出pow(b,0)到pow(b,i) (pow(b,i)<=n)
存到一个数组里,然后用它们将n分解。后来看了柳神的做法,发现完全可以不用计算power,因为在分解n的过程中就可以不断地除以b,而且这样还不用担心int
溢出(当b=时,最后可能需要算b*b来判断是否超过n,这就需要long long
了)。
说的就是这段代码:
int cnt=0; while(n){ v[++cnt]=n%b; n/=b; }
原来我的做法都是在while
里进行类似x*=b
的这种操作。果然是我多项式分解掌握得太不熟练了。
AC代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <string> #include <string.h> #include <vector> using namespace std; int n,b; int v[35]; int main(){ scanf("%d%d",&n,&b); int cnt=0; while(n){ v[++cnt]=n%b; n/=b; } int mid=cnt>>1; bool flag=true; for(int i=cnt;i>cnt-mid;--i) if(v[i]!=v[cnt+1-i]){ flag=false; break; } printf("%s\n",flag?"Yes":"No"); for(int i=cnt;i>1;--i) printf("%d ",v[i]); printf("%d\n",v[1]); return 0; }
本文作者:Ryomk
本文链接:https://www.cnblogs.com/preccrep/p/16348687.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步