【PATB】解pat乙级题目

记:最近为了准备考研机试所以写写PAT习题和CCF题目,为了给自己设置一个进度条,我便想把自己每日做的题目贴上来。一是可以看看自己每天到底学了什么;而来也分享自己的题解。
如果有错误的地方,还请大家指出,非常谢谢!!
T1- PATB1085

1085 PAT单位排行 (25分)
每次 PAT 考试结束后,考试中心都会发布一个考生单位排行榜。本题就请你实现这个功能。
输入格式:
输入第一行给出一个正整数 N(≤10
?5
?? ),即考生人数。随后 N 行,每行按下列格式给出一个考生的信息:
准考证号 得分 学校
其中准考证号是由 6 个字符组成的字符串,其首字母表示考试的级别:B代表乙级,A代表甲级,T代表顶级;得分是 [0, 100] 区间内的整数;学校是由不超过 6 个英文字母组成的单位码(大小写无关)。注意:题目保证每个考生的准考证号是不同的。
输出格式:
首先在一行中输出单位个数。随后按以下格式非降序输出单位的排行榜:排名 学校 加权总分 考生人数
其中排名是该单位的排名(从 1 开始);学校是全部按小写字母输出的单位码;加权总分定义为乙级总分/1.5 + 甲级总分 + 顶级总分*1.5的整数部分;考生人数是该属于单位的考生的总人数。
学校首先按加权总分排行。如有并列,则应对应相同的排名,并按考生人数升序输出。如果仍然并列,则按单位码的字典序输出。
解题方法1:这种解放我视图用一个map存放key=学校,value是人数和加权总分。用到知识点map,vector,pair。 特别注意的是map底层是用红黑树实现的,因此它是按照key来排序的。而这里我们用按照value排序所以我把它存入vector,在排序。可是提交后用一个bug,便是取整的问题。22分
#include #include #include #include #include #include using namespace std; struct cls{ int num; //人数 int sum; //加权分数 }; typedef pair PAIR; struct cmpBycls{ bool operator()(const PAIR& a, const PAIR& b){ if(a.second.sum != b.second.sum){ return a.second.sum>b.second.sum; //按照总加权分数排序 } else if(a.second.num != b.second.num) { return a.second.num < b.second.num; //加权分数相同按照人数升序排序 } else{ return a.first < b.first; // 按照字典序排列 } } }; int main(){ string id; double score; string sh; map mp; int n; scanf("%d", &n); int cnt = 1; while(cnt <= n){ cin>>id>>score>>sh; transform(sh.begin(),sh.end(),sh.begin(),::tolower); mp[sh].num++; switch(id[0]){ case 'A': mp[sh].sum += score; break; case 'B': mp[sh].sum += (score / 1.5); break; case 'T': mp[sh].sum += (score * 1.5); break; } cnt++; } vector vv(mp.begin(),mp.end()); sort(vv.begin(),vv.end(),cmpBycls()); //给向量排序 /*for(vector::iterator it=vv.begin(); it != vv.end(); it++){ cout<first<<" "<second.num<< " "<< it->second.sum<0 && vv[i-1].second.sum != vv[i].second.sum){ count = i + 1; } cout<

解法2:使用两个map
#include #include #include #include #include #include using namespace std; /* 使用两个map来分别保存人数和分数 */ struct node{ string school; int sum,num; }; bool cmp(node a,node b){ if(a.sum != b.sum){ return a.sum > b.sum; }else if(a.num != b.num){ return a.num < b.num; }else{ return a.school < b.school; } } int main(){ string id,school; double score; map mp; map mp2; int n; scanf("%d",&n); int cnt = 1; while(cnt <= n){ cin>>id; scanf("%lf",&score); cin>>school; for(int i = 0; i < school.length(); i++){ school[i] = tolower(school[i]); } if(id[0] == 'B'){ score /= 1.5; } if(id[0] == 'T'){ score *= 1.5; } mp[school] += score; //总加权分数 mp2[school]++; //人数+1 cnt++; } //将map中数据填入vector中 vector ans; for(map::iterator it = mp.begin(); it != mp.end(); it++){ ans.push_back(node{it->first,(int)mp[it->first], mp2[it->first]}); } sort(ans.begin(),ans.end(),cmp); int rank = 1; cout< 0 && ans[k].sum != ans[k-1].sum){ rank = k + 1; } printf("%d ",rank); cout<

T2 PATB1032
1032 挖掘机技术哪家强 (20分)
为了用事实说明挖掘机技术到底哪家强,PAT 组织了一场挖掘机技能大赛。现请你根据比赛结果统计出技术最强的那个学校。
输入格式:
输入在第 1 行给出不超过 10
?5
?? 的正整数 N,即参赛人数。随后 N 行,每行给出一位参赛者的信息和成绩,包括其所代表的学校的编号(从 1 开始连续编号)、及其比赛成绩(百分制),中间以空格分隔。
输出格式:
在一行中给出总得分最高的学校的编号、及其总分,中间以空格分隔。题目保证答案唯一,没有并列。
题解思路还是按照map来映射,最后在排序一下。
#include #include #include #include #include using namespace std; struct node{ int key,value; }; bool cmp(node a,node b){ return a.value > b.value; } int main(){ map mp; int n; scanf("%d", &n); int cnt = 1; int key,value; while(cnt <= n){ scanf("%d %d",&key, &value); mp[key] += value; cnt++; } vector ans; for(map::iterator it = mp.begin(); it != mp.end(); it++){ ans.push_back(node{it->first,mp[it->first]}); } sort(ans.begin(),ans.end(),cmp); cout<

T3-PATB1083
1082 射击比赛 (20分)
本题目给出的射击比赛的规则非常简单,谁打的弹洞距离靶心最近,谁就是冠军;谁差得最远,谁就是菜鸟。本题给出一系列弹洞的平面坐标(x,y),请你编写程序找出冠军和菜鸟。我们假设靶心在原点(0,0)。
解题思路:依然可以用map,在排序
#include #include #include #include #include #include using namespace std; struct node{ string id; double dis; }; bool cmp(node a,node b){ return a.dis>id; scanf("%d %d",&x,&y); mp[id] = abs(x*x)+ abs(y*y); cnt++; } vector ans; for(map::iterator it = mp.begin(); it != mp.end(); it++){ ans.push_back(node{it->first,mp[it->first]}); } sort(ans.begin(),ans.end(),cmp); int last = ans.size()-1; cout<

T4-PAT1081
【【PATB】解pat乙级题目】1081 检查密码 (15分)
本题要求你帮助某网站的用户注册模块写一个密码合法性检查的小功能。该网站要求用户设置的密码必须由不少于6个字符组成,并且只能有英文字母、数字和小数点 .,还必须既有字母也有数字。
【说明】这道题开始想用regex,可是我用的编译器不知处c++11特性。
其次这道题目我开始没用c提供的ctype库,直接写判断。后来参考其他人博客,才开始写了第二版judge()使用isalnum(),isalpha(),isdigt()
#include #include #include #include #include #include #include using namespace std; /* 该网站要求用户设置的密码必须由不少于6个字符组成, 并且只能有英文字母、数字和小数点 . 还必须既有字母也有数字 */ /* void judge(string s){ string ans; bool flag1 = false,flag2 = false; if(s.length() < 6){ ans += "Your password is tai duan le."; cout<= 'a' && s[i] <= 'z' || s[i] >= 'A' && s[i] <= 'Z'){ flag1 = true; }else if(s[i] >= '0' && s[i] <= '9'){ flag2 = true; }else if(s[i] != '.'){ ans += "Your password is tai luan le."; cout<= 6){ for(int i = 0; i < s.length(); i++){ if(s[i] != '.' && !isalnum(s[i])) { invalid = 1; break; }else if(isalpha(s[i])){ hasalpha = 1; }else if(isdigit(s[i])){ hasnum = 1; } } if(invalue =https://www.it610.com/article/= 1){ count<<"Your password is tai luan le."<>s; getline(cin,s); judge(s); cnt++; } return 0; }

T4-PATB1079
1079 延迟的回文数 (20分)
给定一个 k+1 位的正整数 N,写成 a0??的形式,其中对所有 i 有 0≤ai<10 且 ak?? >0。N 被称为一个回文数,当且仅当对所有 i 有 ai=ak?i 。零也被定义为一个回文数。
非回文数也可以通过一系列操作变出回文数。首先将该数字逆转,再将逆转数与该数相加,如果和还不是一个回文数,就重复这个逆转再相加的操作,直到一个回文数出现。如果一个非回文数可以变出回文数,就称这个数为延迟的回文数。
给定任意一个正整数,本题要求你找到其变出的那个回文数。
解题思路:1.回文字符串的判断 2.注意测试点4,6使用大整数
第一次直接使用int结果没过4,6.
#include #include #include #include #include #include using namespace std; /* 延迟的回文数 */ int r_num(int num){ int sum = 0; int i = 0; while(num > 0){ sum = sum*10 + num%10; num /= 10; } return sum; } bool isPal(int num){ //判断是否回文 // string s = to_string(num); int ans[1001]; int cnt = 0; while(num > 0){ ans[cnt++] = num % 10; num /= 10; } for(int i = 0; i < cnt / 2; i++){ if(ans[i] != ans[cnt-i-1]){ return false; } } return true; } int main(){ int num; int cnt = 1; scanf("%d",&num); while(1){ if(isPal(num)){ cout< 10){ cout<<"Not found in 10 iterations."; break; }else{ // printf(""); // num = num + r_num(num); int a = num; int b = r_num(num); int c = a + b; printf("%d + %d = %d\n",a,b,c); num = c; cnt++; } } } return 0; }

满分版,使用大整数相加的思路,注意进位标记。
#include #include #include #include #include #include using namespace std; /* 这里要注意测试点4和6,是用大数测试的 */ bool isPal(string s){ int len = s.length(); for(int i = 0; i < len; i++){ if(s[i] != s[len-i-1]){ return false; } } return true; }string cal(string a, string b){ string str; int cx = 0; int len = a.length(); for(int i = 0; i < len; i++){ int aa = a[i] - '0'; int bb = b[i] - '0'; int cc = aa + bb + cx; cx = 0; if(cc >= 10){ cx = 1; cc -= 10; } str += char(cc + '0'); } if(cx == 1){ str += '1'; } reverse(str.begin(),str.end()); return str; } int main() { string s; cin>>s; getchar(); int cnt = 1; while(1){ if(isPal(s)){ //是回文字符串,直接输出 cout< 10){ //输出 cout<<"Not found in 10 iterations."< T6-PATB1083
1083 是否存在相等的差 (20分)
给定 N 张卡片,正面分别写上 1、2、……、N,然后全部翻面,洗牌,在背面分别写上 1、2、……、N。将每张牌的正反两面数字相减(大减小),得到 N 个非负差值,其中是否存在相等的差?
注意使用反向迭代器。
#include #include #include #include using namespace std; /* PAT1083 是否存在相等的差 1 2 3 4 5 6 7 8 3 5 8 6 2 1 4 7 2 3 5 2 3 5 3 1 用到stl中的map,并使用反向输出迭代器 */ using namespace std; int main(){ int n ; map mp; scanf("%d",&n); int cnt = 1; int temp; while(cnt <= n){ scanf("%d",&temp); int key = abs(temp-cnt); mp[key]++; cnt++; } for(map::reverse_iterator rit = (mp.rbegin()); rit != mp.rend(); rit++){ if((*rit).second > 1){ printf("%d %d\n",rit->first, rit->second); } } return 0; }

    推荐阅读