📂刷题
🔖PAT
2022-06-08 09:32阅读: 29评论: 0推荐: 0

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分
万恶的模拟题,对我这种总是看不懂题/存在理解偏差/看漏条件的人极不友好。
还有亿点点细节需要注意。
坑点合集:

  1. 按照时间排序后,两个可以匹配的记录中第一个一定是online,第二个是offline
  2. toll的单位是“美分/分钟”,而且注意每个toll代表的区间是什么。最好从0开始存储。
  3. 话费的计算:我的方法是,先计算天数差需要的钱,然后分别减去左端点和加上右端点(看代码应该秒懂)
    看到有的博客说最后算出的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=109时,最后可能需要算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 中国大陆许可协议进行许可。

posted @   Ryomk  阅读(29)  评论(0编辑  收藏  举报
评论
收藏
关注
推荐
深色
回顶
收起
点击右上角即可分享
微信分享提示
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.

作曲 : Reol

作词 : Reol

fade away...do over again...

fade away...do over again...

歌い始めの一文字目 いつも迷ってる

歌い始めの一文字目 いつも迷ってる

どうせとりとめのないことだけど

伝わらなきゃもっと意味がない

どうしたってこんなに複雑なのに

どうしたってこんなに複雑なのに

噛み砕いてやらなきゃ伝わらない

ほら結局歌詞なんかどうだっていい

僕の音楽なんかこの世になくたっていいんだよ

Everybody don't know why.

Everybody don't know why.

Everybody don't know much.

僕は気にしない 君は気付かない

何処にももういないいない

Everybody don't know why.

Everybody don't know why.

Everybody don't know much.

忘れていく 忘れられていく

We don't know,We don't know.

目の前 広がる現実世界がまた歪んだ

目の前 広がる現実世界がまた歪んだ

何度リセットしても

僕は僕以外の誰かには生まれ変われない

「そんなの知ってるよ」

気になるあの子の噂話も

シニカル標的は次の速報

麻痺しちゃってるこっからエスケープ

麻痺しちゃってるこっからエスケープ

遠く遠くまで行けるよ

安定なんてない 不安定な世界

安定なんてない 不安定な世界

安定なんてない きっと明日には忘れるよ

fade away...do over again...

fade away...do over again...

そうだ世界はどこかがいつも嘘くさい

そうだ世界はどこかがいつも嘘くさい

綺麗事だけじゃ大事な人たちすら守れない

くだらない 僕らみんなどこか狂ってるみたい

本当のことなんか全部神様も知らない

Everybody don't know why.

Everybody don't know why.

Everybody don't know much.

僕は気にしない 君は気付かない

何処にももういないいない

Everybody don't know why.

Everybody don't know why.

Everybody don't know much.

忘れていく 忘れられていく

We don't know,We don't know.