转载请注明出处:https://www.cnblogs.com/jlyg/p/7525244.html
终于在考前,刷完PAT甲级131道题目,不容易!!!每天沉迷在刷题之中而不能超脱,也是一种境界。PAT甲级题目总的说卡题目的比较多,卡测试点的比较少,有些题目还会有题意混淆,这点就不吐槽了吧。静下心来耍这130道题,其实磨练的是一种态度与手感,养成的是一种习惯。热爱AC没有错!!(根据自己的刷题情况持续更新中,这次是第二遍刷了,发现换了新网站后,oj严格很多了,有些之前可以过的,现在已经不能过了)
PAT甲级复习之二:主要写一些考前注意,以及常见算法。网址通道https://www.cnblogs.com/jlyg/p/10364696.html。
PAT甲级复习之三:主要是131题后的题目,网址通道https://www.cnblogs.com/jlyg/p/10364727.html
131道题目主要的考点:
1、排序:快速排序,直接插入排序,希尔排序,分治排序,堆排序。
2、图论:拓扑排序(好像没考过)、最短路径、深度搜索、广度搜索。
3、树:树的遍历、完全二叉树、AVL,CBT,BST。
4、其他:并查集,模拟,哈希(二次探测一次,简单hash多次)、背包(一次),lcs(一次),最大子和(一次),set(一次),1057(分块搜索)
主要算法:快排、直接插入排序、希尔排序、分治排序、堆排序、拓扑排序、dijkstra,floyd,dfs,bfs,AVL,并查集,树遍历算法。
题目分类:
1003(dfs or dijkstra)、1004(dfs)、1007(最长子和)、1010(二分查找)、1013(并查集)、1020(二叉树,前后序求广度)、1021(并查集)、1024(大数加法)、1029(归并排序)、1030(dikstra)、1043(前序判断是否是二叉收缩树)、1044(二分查找)、1045(lcs)、1053(dfs)、1063(set)、1064(二叉搜索树)、1066(AVL)、1068(背包问题)、1076(bfs)、1078(hash二次探测)、1079(bfs,dfs)、1086(中前序求后序)、1089(排序)、1094(bfs or 并查集),1098(排序)、1099(BST)、1101(快排)、1102(反转二叉树)、1103(dfs剪枝)、1107(并查集)、1110(完全二叉树)、1111(dijkstra)、1114(并查集)、1115(BST)、1118(并查集)、1119(前后序求中序)、1123(AVL)、1127(bfs)、1130(dfs) dijkstra: 1003、1030、1111 dfs: 1003、1004、1053、1079、1103(dfs剪枝)、1130 bfs:1076、1079、1094、1127 排序:1029(归并排序)、1089、1098、1101(快排) 并查集:1013、1021、1094、1107、1114、1118 二叉树:1020(前后序求广度)、1043(前序判断是否是二叉搜索树)、1064(二叉搜索树)、1066(AVL)、1086(中前序求后序)、1099(BST)、1102(反转二叉树)、1110(完全二叉树)、1115(BST)、1119(前后序求中序)、1123(AVL) 二分查找:1010、1044 其他:1007(最长子和)、1024(大数加法)、1045(lcs)、1063(set)、1068(背包问题)、1078(hash二次探测)
错误修改:1013不是并查集,应该是dfs,刚刚发现,抱歉。
1010这题目会比较奇怪,属于题意不清,第一可能会超出long long int,第二需要使用二分法不然超时,第三进制是无限制的可以是2到无限
#include<iostream> #include<cstdio> #include<set> #include<map> #include<vector> #include<iterator> #include<algorithm> #include<cstring> using namespace std; long long int change(const char* strnum,long long int jinzhi) { long long int len = strlen(strnum); long long int res = 0; for(long long int i=len-1,k=1;i>=0;--i,k*=jinzhi) { long long int a; if(strnum[i]>='0'&& strnum[i]<='9') a = strnum[i]-'0'; else a = strnum[i]-'a'+10; res += k*a; } return res; } long long int Find_Radix(char* strnum,long long int dst,long long int left,long long int right) { long long int mid = (left+right)/2; long long int midnum = change(strnum,mid); if(left==right) { if(dst != midnum) return -1; return left; } else if(left > right) { return -1; } if(midnum==dst) { return mid; } if(midnum<0||dst<midnum) { return Find_Radix(strnum,dst,left,mid-1); } else { return Find_Radix(strnum,dst,mid+1,right); } } int main() { //freopen("test.txt","r",stdin); char s1[20],s2[20]; int tag,jinzhi; scanf("%s%s%d%d",s1,s2,&tag,&jinzhi); if(tag==2) {swap(s1,s2);} long long int a = change(s1,jinzhi); long long int left = 0; int len = strlen(s2); for(int i=0;i<len;++i) { long long int temp; if(s2[i]>='0'&&s2[i]<='9') { temp = s2[i]-'0'; } else { temp = s2[i] - 'a'+10; } left = max(temp+1,left); } left = max((long long int)2,left); long long int right = max(a,left); long long int res = Find_Radix(s2,a,left,right); if(res==-1) { printf("Impossible "); } else { printf("%lld ",res); } return 0; }
1012题目排名是可以有并列的,比如有并列第1的情况。
1014这道题的问题在于只要在17:00之前开始的就是正常的,结束时间是可以超过17:00后的,有点坑吧。
1017模拟题,看代码和注释,很详细
#include<iostream> #include<cstdio> #include<set> #include<map> #include<vector> #include<iterator> #include<algorithm> #include<cstring> using namespace std; int gettick(int h,int m,int s) { return h*60*60+m*60+s; } const int window_starttime = gettick(8,0,0); const int window_endtime = gettick(17,0,0); struct Customer { int cometime; //来到时间 int protime; //处理时间,秒 }; int getfreewindow(int* windows,int k) { int mintime = windows[0],mink = 0; for(int i=1;i<k;++i) { if(mintime > windows[i]) { mink = i; mintime = windows[i]; } } //注释1:该种情况就是,这个人是17点之前来的,但是前面有人结束后就已经是17点以后了,这种情况也不需要过滤,还是计算在内的。 //if(mintime>window_endtime) return -1; return mink; } int cmp(const Customer& c1,const Customer& c2) { return c1.cometime < c2.cometime; } int main() { #ifdef ONLINE_JUDGE #else freopen("test.txt","r",stdin); #endif int n,k; scanf("%d%d",&n,&k); vector<Customer> vcus; for(int i=0;i<n;++i) { int h,m,s,p; scanf("%d:%d:%d%d",&h,&m,&s,&p); Customer cus; cus.cometime = gettick(h,m,s); cus.protime = min(60*p,60*60); if(cus.cometime <= window_endtime) //过滤17点以后来的人 vcus.push_back(cus); } n = vcus.size(); sort(vcus.begin(),vcus.end(),cmp); int twaittime = 0/*总等待时间*/,cnt=0/*得到处理的人数*/,windowstime[k]/*该窗口空闲时间*/; for(int i=0;i<k;++i) windowstime[i] = window_starttime; for(int i=0;i<n;++i) { int iw = getfreewindow(windowstime,k); if(iw==-1) break; ++cnt; Customer &cus = vcus[i]; if(cus.cometime<windowstime[iw]) { twaittime+= (windowstime[iw]-cus.cometime); windowstime[iw] += cus.protime; } else { windowstime[iw] = cus.cometime + cus.protime; } } if(cnt==0) printf("0.0 "); else printf("%.1lf ",1.0f*twaittime/cnt/60); return 0; }
1018题:dfs,求最小路径,若相同求最小借出的bike数,再若相同,求最小还回的bike数。要注意路径(cmax=10)PBM->(3)->(10),它的send为2,back为5,而不是send为0,back3(后面多出来的不能补到前面的,前面多出来的可以补到后面)
#include<iostream> #include<cstdio> #include<set> #include<map> #include<vector> #include<iterator> #include<algorithm> #include<cstring> using namespace std; #define N (510) const int INF = (1<<30); int cmax,n,sp,m; int cap[N]; int Len[N][N]; vector<int> Map[N]; bool bVis[N]; int minlen = INF; int minsend = 0; int minback= 0; vector<int> minPath; void dfs(int curI,int len,vector<int> path) { if(curI==sp) { if(len <= minlen) { int curminsend = 0,curminback = 0; for(int i=1;i<path.size();++i) { int curcap = cap[path[i]]; if(curcap<cmax/2) //少了 { int adjust = cmax/2 - curcap; if(adjust <= curminback) { curminback -= adjust; } else { adjust -= curminback; curminback = 0; curminsend += adjust; } } else if(curcap>cmax/2) //多了 { curminback += (curcap-cmax/2); } } if(len<minlen||(len==minlen&&curminsend<minsend)|| (len==minlen&&curminsend==minsend&&curminback<minback)) { minlen = len; minPath = path; minsend = curminsend; minback = curminback; } } return; } if(len >= minlen) return; for(int i=0;i<Map[curI].size();++i) { int nextI = Map[curI][i]; if(!bVis[nextI]) { bVis[nextI] = true; path.push_back(nextI); dfs(nextI,len+Len[curI][nextI],path); path.pop_back(); bVis[nextI] = false; } } } int main() { #ifdef ONLINE_JUDGE #else freopen("test.txt","r",stdin); #endif scanf("%d%d%d%d",&cmax,&n,&sp,&m); for(int i=0;i<=n;++i) for(int j=0;j<=n;++j) if(i==j) Len[i][j] = 0; else Len[i][j] = INF; for(int i=1;i<=n;++i) scanf("%d",&cap[i]); for(int i=0;i<m;++i) { int a,b,l; scanf("%d%d%d",&a,&b,&l); Len[a][b] = Len[b][a] = l; Map[a].push_back(b); Map[b].push_back(a); } bVis[0] = true; vector<int> path; path.push_back(0); dfs(0,1,path); printf("%d ",minsend); for(int i=0;i<minPath.size();++i) { if(i) printf("->"); printf("%d",minPath[i]); } printf(" %d ",minback); return 0; }
1022题,需要用到整行输入字符串,而PAT的c++编译器是无法调用gets的,可以用fgets(buf,sizeof(buf),stdin);//读入的数据需要去掉
。如果在fgets函数之前调用了scanf,就必须要使用getchar把换行好读掉。
当然也可以用 while
(cin>>str)
{
char
c;
c=
getchar
();
if
(c==
'
'
)
break
;
}
#include<iostream> #include<cstdio> #include<set> #include<map> #include<vector> #include<iterator> #include<algorithm> #include<cstring> using namespace std; void mygets(string& str) { char temp[100]; fgets(temp,sizeof(temp),stdin); temp[strlen(temp)-1] = '