PAT甲级 排序题_C++题解
排序题
PAT (Advanced Level) Practice 排序题
目录
- 《算法笔记》 6.9.6 sort()用法
- 《算法笔记》 4.1 排序题步骤
- 1012 The Best Rank (25)
- 1083 List Grades (25)
- 1137 Final Grading (25)
- 1141 PAT Ranking of Institutions (25)
- 1153 Decode Registration Card of PAT (25)
《算法笔记》 6.9.6 sort()
#include<algorithm>
using namespace std;
void sort (first, last, cmp);
// first 首元素地址;last 尾元素地址下一个地址;cmp 比较函数
《算法笔记》 4.1 排序题步骤
1. 相关结构体的定义
struct Student {
char name[10];
char id[10];
int score;
int rank;
}stu[10000];
2. cmp函数的编写
分数不同分数高在前,分数相同姓名字典序小在前
bool cmp(Student a, Student b){
return a.score != b.score ? a.score > b.score : strcmp(a.name, b.name) < 0;
}
3. 排名的实现
分数不同排名不同,分数相同排名相同占用同一个排位
(1) 记录在结构体中
- 将数组第一个个体排名记为 1
- 遍历剩余个体,若当前个体分数 = 上一个个体分数,则当前个体排名 = 上一个体排名;
- 若当前个体分数 != 上一个体分数,则排名 = 数组下标 + 1
stu[0].rank = 1;
for (int i = 1; i < n; i++){
if (stu[i].score == stu[i-1].score) stu[i].rank = stu[i-1].rank;
else stu[i].rank = i + 1;
}
(2) 直接输出
int rank = 1;
for (int i = 0; i < n; i++)
if (i > 0 && stu[i].score != stu[i-1].score)
rank = i + 1;
1012 The Best Rank (25)
#include<unordered_map>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
struct Student{
int id, best;
int score[4], rank[4];
};
int sortby = -1;
bool cmp (Student a, Student b) { return a.score[sortby] > b.score[sortby];};
int main()
{
int n, m, id;
scanf("%d%d",&n,&m);
vector<Student> stu(n+1);
for (int i = 0; i < n; i++){
scanf("%d%d%d%d",&stu[i].id,&stu[i].score[1],&stu[i].score[2],&stu[i].score[3]);
stu[i].score[0] = (stu[i].score[1] + stu[i].score[2] + stu[i].score[3]) / 3;
}
for (sortby = 0; sortby < 4; sortby++){
sort(stu.begin(),stu.end(),cmp);
stu[0].rank[sortby] = 1;
for (int i = 1; i < n; i++){
if (stu[i].score[sortby] != stu[i-1].score[sortby]) stu[i].rank[sortby] = i+1;
else stu[i].rank[sortby] = stu[i-1].rank[sortby];
}
}
unordered_map<int, int> index;
for (int i = 0; i < n; i++){
index.insert(pair<int,int>(stu[i].id,i));
stu[i].best = 0;
int minr = stu[i].rank[0];
for (int j = 1; j < 4; j++){
if (stu[i].rank[j] < minr){
stu[i].best = j;
minr = stu[i].rank[j];
}
}
}
char symbol[] = "ACME";
for (int i = 0; i < m; i++){
scanf("%d",&id);
if (index.find(id) == index.end()) printf("N/A\n");
else{
int best = stu[index[id]].best;
printf("%d %c\n",stu[index[id]].rank[best], symbol[best]);
}
}
return 0;
}
简化代码(参考柳婼小姐姐的代码)
- 题目中平均分取整数,所以结构体中的分数信息均为 int 型,可用数组表示;同理依据不同分数进行的排名信息也可以用数组表示。
- 对四种分数进行排序+排名需要四个不同的比较函数较为重复,且排序依据在数组中完全可以用数组下标移动来表示不同的比较依据。
- 向 sort() 传入的 cmp() 参数固定不能增加,设置全局变量 sortby
- 在 cmp() 中依据全局变量变化比较依据,在程序主体控制 sortby 以比较不同分数
- 要比较四个不同的排名选择其中最好的,在结构体中设置变量 best 记录对应分数下标
- 四种分数用一个简单的选择排序选出 best 进行赋值
- 最后输出时依据记录的 best 到结构体自己的 rank 数组中输出最好的排名值 及 到字符数组 symbol 中输出对应的科目标识
- 字符数组初始化问题 -> 笔记:3.5进制转换题 1027 Colors in Mars
- 本题 id 可用整型表示,所以查找时相当于建立 int->int 的映射,可以直接开大数组做散列查找。
- 由于之前将 id 设为 string 型,仍然使用 map,由于只用 map 做映射不做排序,可用 unordered_map
- 注意添加映射关系要在处理完所有排名赋值后,否则sort会打乱排序,映射关系出错。
- 要对 vector 使用 [] 访问进行赋值必须给出大小,不给大小只能用 push_back 添加元素
简化前代码如下
#include<unordered_map>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
struct Student{
string id;
int c, math, eng;
double avg;
int r_c, r_math, r_eng, r_avg;
Student (){}
Student (string _id, int _c, int _math, int _eng): id(_id), c(_c), math(_math), eng(_eng){
avg = (c + math + eng) / 3.0;
}
};
bool cmp_c (Student a, Student b){ return a.c > b.c;}
bool cmp_math (Student a, Student b){ return a.math > b.math;}
bool cmp_eng (Student a, Student b){ return a.eng > b.eng;}
bool cmp_avg (Student a, Student b){ return a.avg > b.avg;}
int main()
{
int n, m, c, math, eng;
string id;
cin >> n >> m;
vector<Student> stu;
unordered_map<string, int> index;
for (int i = 0; i < n; i++){
cin >> id >> c >> math >> eng;
stu.push_back(Student(id,c,math,eng));
}
sort(stu.begin(),stu.end(),cmp_c);
stu[0].r_c = 1;
for (int i = 1; i < n; i++){
if (stu[i].c == stu[i-1].c) stu[i].r_c = stu[i-1].r_c;
else stu[i].r_c = i+1;
}
sort(stu.begin(),stu.end(),cmp_math);
stu[0].r_math = 1;
for (int i = 1; i < n; i++){
if (stu[i].math == stu[i-1].math) stu[i].r_math = stu[i-1].r_math;
else stu[i].r_math = i+1;
}
sort(stu.begin(),stu.end(),cmp_eng);
stu[0].r_eng = 1;
for (int i = 1; i < n; i++){
if (stu[i].eng == stu[i-1].eng) stu[i].r_eng = stu[i-1].r_eng;
else stu[i].r_eng = i+1;
}
sort(stu.begin(),stu.end(),cmp_avg);
stu[0].r_avg = 1;
index.insert(pair<string,int>(stu[0].id,0));
for (int i = 1; i < n; i++){
if (stu[i].avg == stu[i-1].avg) stu[i].r_avg = stu[i-1].r_avg;
else stu[i].r_avg = i+1;
index.insert(pair<string,int>(stu[i].id,i));
}
for (int i = 0; i < m; i++){
cin >> id;
if (index.find(id) == index.end()) cout << "N/A\n";
else{
int min_r = min(min(min(stu[index[id]].r_c,stu[index[id]].r_math),stu[index[id]].r_eng),stu[index[id]].r_avg);
cout << min_r << " ";
if (min_r == stu[index[id]].r_avg) cout << "A\n";
else if (min_r == stu[index[id]].r_c) cout << "C\n";
else if (min_r == stu[index[id]].r_math) cout << "M\n";
else cout << "E\n";
}
}
return 0;
}
1083 List Grades (25)
题目思路
- 按成绩从大到小排序,排序后过滤输出。
- 设置变量记录是否找到了值,没找到输出 NONE
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct Student{
string name, id;
int grade;
};
bool cmp(Student a, Student b){ return a.grade > b.grade; }
int main()
{
int n, grade, min, max;
scanf("%d", &n);
string name, id;
vector<Student> list;
for (int i = 0; i < n; i++){
cin >> name >> id >> grade;
list.push_back({name, id, grade});
}
sort(list.begin(), list.end(), cmp);
scanf("%d%d", &min, &max);
bool empty = true;
for (int i = 0; i < list.size(); i++){
if (list[i].grade < min) break;
if (list[i].grade > max) continue;
if (empty) empty = false;
cout << list[i].name << " " << list[i].id << endl;
}
if (empty) printf("NONE\n");
return 0;
}
曾经清奇的脑回路Orz
- 利用成绩唯一性,以成绩为 key 将姓名学号信息存入 map
- 利用
map.lower_bound()和map.upper_bound()输出要求信息
#include<iostream>
#include<map>
using namespace std;
int main(){
map<int,string,greater<int>> records;
int n, grade, min, max;
string name, ID;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
cin >> name >> ID >> grade;
records.insert(pair<int,string>(grade,name + " " + ID));
}
scanf("%d%d", &min, &max);
if (records.lower_bound(max) == records.upper_bound(min))
cout << "NONE" << endl;
else
for (auto it = records.lower_bound(max); it != records.upper_bound(min); ++it)
cout << it->second << endl;
return 0;
}
1137 Final Grading (25)
题目思路
- 将不同分数分别放到 map 中存储
- 首要筛选编程分数低于 200 的,取记录编程分数的 map 进行遍历
- 若编程分数低于 200,或没有登入期末考成绩,不可能合格,continue 跳过
- 剩余都有期末考成绩,再看是否有期中成绩,若有看是否高于期末,若是则按比例计算总评,若不是则期末分数即为总评分数
- 依据四舍五入后的总评将学生信息压入结构体容器,注意检查期中考可能无成绩要登入 -1
- 对结构体数据进行排序后按标准输出
- 坑点(最后一个测试点):由于要根据总评是否达到 60 决定这个学生是否会加入到及格容器,所以要在判断前进行四舍五入,而非用 double 型作判断后压入容器才四舍五入,这样会损失部分 [59.5,60) 的学生
#include<iostream>
#include<unordered_map>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
struct Student{
string id;
int p, mid, final, grade;
};
bool cmp(Student a, Student b) { return a.grade != b.grade ? a.grade > b.grade : a.id < b.id; }
int main()
{
int p, m, n, score;
scanf("%d%d%d", &p, &m, &n);
unordered_map<string,int> program, mid, final;
string id;
for (int i = 0; i < p; i++){
cin >> id >> score;
if (score <= 900) program.insert({id,score});
}
for (int i = 0; i < m; i++){
cin >> id >> score;
if (score <= 100) mid.insert({id,score});
}
for (int i = 0; i < n; i++){
cin >> id >> score;
if (score <= 100) final.insert({id,score});
}
vector<Student> list;
for (auto it: program){
string id = it.first;
if (it.second < 200 || final.find(id) == final.end()) continue;
if (mid.find(id) != mid.end() && mid[id] > final[id]) score = round(mid[id]*0.4 + final[id]*0.6);
else score = final[id];
if (score >= 60) list.push_back({id,it.second,mid.find(id)==mid.end()?-1:mid[id],final[id],score});
}
sort(list.begin(), list.end(), cmp);
for (auto it: list) printf("%s %d %d %d %d\n", it.id.c_str(), it.p,it.mid,it.final,it.grade);
return 0;
}
1141 PAT Ranking of Institutions (25)
题目思路
- 用两个 map 分别记录每个学校对应的参考人数和总分
- map 的 key 值不重复,不需要单独开 set 记录学校 id,只要遍历两个 map 中的一个,将相关信息放到结构体容器中即可
- 用 sort 对容器排序,由于排名只需要输出不需要记录,可以不记录结构体中而是用变量 rank 记录并输出即可
- 坑点:由于不同等级分数换算,总分应当用 double 而非 int 来存,全部计算求和完毕后,压入容器排序前再转换为 int
#include<iostream>
#include<unordered_map>
#include<vector>
#include<algorithm>
using namespace std;
struct School{
string ID;
int TWS, Ns;
};
bool cmp (School a, School b){
return a.TWS != b.TWS ? a.TWS > b.TWS : a.Ns != b.Ns ? a.Ns < b.Ns : a.ID < b.ID;
}
int main()
{
unordered_map<string,int> ns;
unordered_map<string,double> tws;
string id, school;
int n, score, rank = 1;
scanf("%d\n", &n);
for (int i = 0; i < n; i++){
cin >> id >> score >> school;
transform(school.begin(), school.end(), school.begin(), ::tolower);
ns[school]++;
if (id[0] == 'T') tws[school] += score * 1.5;
else if (id[0] == 'A') tws[school] += score;
else tws[school] += score / 1.5;
}
vector<School> ranklist;
for (auto it = ns.begin(); it != ns.end(); it++){
ranklist.push_back({it->first, (int)tws[it->first], it->second});
}
sort(ranklist.begin(), ranklist.end(), cmp);
printf("%d\n%d %s %d %d\n", ranklist.size(), rank, (ranklist[0].ID).c_str(), ranklist[0].TWS, ranklist[0].Ns);
for (int i = 1; i < ranklist.size(); i++){
if (ranklist[i].TWS != ranklist[i-1].TWS) rank = i + 1;
printf("%d %s %d %d\n", rank, (ranklist[i].ID).c_str(), ranklist[i].TWS, ranklist[i].Ns);
}
return 0;
}
- 中
transform(word.begin(),word.end(),new_word.begin(),op);要转化为大写,op = ::toupper,因 toupper 是在全局命名空间而非 std 中,所以要加 :: - 结构体初始化
- 顺序初始化:不写构造函数,直接用 {} 按顺序传入参数即可初始化
- 构造函数初始化:写了构造函数可以用()选择性传参
- 注意写了构造函数就不可以用顺序初始化了
运行超时
- 有 map 改为 unordered_map
- 能用 scanf/printf 的不用 cin/cout
- 排名只需要输出就不存进结构体,减少一次遍历
1153 Decode Registration Card of PAT (25)
题目思路
- 将所有考生信息接收到结构体容器中,利用构造函数分别赋值便于后面查询。
- 第1种 query:直接按分数-准考证号标准将所有级别考生信息一起排序,然后遍历时检查符合 query 输入的 level 就输出
- 第2种 query:可以在输入时计算好,后面直接查询即可
- 第3种 query:
- 先遍历一遍所有考生信息,符合输入的日期就将对应的考场号人数++
- 所有考生检查完毕后遍历所有考场将考生人数不为0的压入vector
- 依照考生数-考场号标准进行排序,排序后输出
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct CardNumber{
string cardnum, date;
char level;
int site, testeenum, score;
CardNumber(string _cardnum, int _score): cardnum(_cardnum), score(_score){
level = _cardnum[0];
site = stoi(_cardnum.substr(1,3));
date = _cardnum.substr(4,6);
testeenum = stoi(_cardnum.substr(10,3));
}
};
struct SiteNum{
int site, num;
SiteNum(int _site, int _num): site(_site), num(_num) {}
};
bool cmp_card(CardNumber a, CardNumber b){ return a.score != b.score ? a.score > b.score : a.cardnum < b.cardnum; }
bool cmp_site(SiteNum a, SiteNum b){ return a.num != b.num ? a.num > b.num : a.site < b.site; }
int main()
{
int n, m, score, site_tnum[1000] = {0}, site_tscore[1000] = {0};
string cardnum;
scanf("%d%d", &n, &m);
vector<CardNumber> info;
for (int i = 0; i < n; i++){
cin >> cardnum >> score;
info.push_back(CardNumber(cardnum,score));
site_tnum[info[i].site]++;
site_tscore[info[i].site] += score;
}
sort(info.begin(), info.end(), cmp_card);
int type, site;
char level;
string date;
for (int i = 0; i < m; i++){
scanf("%d ", &type);
bool isempty = true;
switch(type){
case 1:
scanf("%c",&level);
printf("Case %d: %d %c\n", i+1, type, level);
for (int j = 0; j < n; j++){
if (info[j].level == level){
isempty = false;
cout << info[j].cardnum << " " << info[j].score << endl;
}
}
if (isempty) printf("NA\n");
break;
case 2:
scanf("%d",&site);
printf("Case %d: %d %d\n", i+1, type, site);
if (!site_tnum[site]) printf("NA\n");
else printf("%d %d\n", site_tnum[site], site_tscore[site]);
break;
case 3:
cin >> date;
cout << "Case " << i+1 << ": " << type << " " << date << endl;
int datesitenum[1000] = {0};
vector<SiteNum> dsn;
for (int j = 0; j < n; j++){
if (info[j].date == date){
isempty = false;
datesitenum[info[j].site]++;
}
}
if (isempty) printf("NA\n");
else{
for (int j = 0; j < 1000; j++) if (datesitenum[j]) dsn.push_back(SiteNum(j,datesitenum[j]));
sort(dsn.begin(),dsn.end(),cmp_site);
for (int j = 0; j < dsn.size(); j++) printf("%d %d\n", dsn[j].site, dsn[j].num);
}
break;
}
}
return 0;
}
- 注意结构体构造函数初始化表写法
- cmp函数中一个 if-else 语句可转为三目运算
- scanf("%c") 会接收空白符,故输入 type 后的空格应写入 scanf 语句,否则用 scanf 接收第1种 query 时,char 型的 level 值无法接收
PAT甲级 排序题_C++题解的更多相关文章
- PAT甲级 链表题_C++题解
链表处理 PAT (Advanced Level) Practice 链表题 目录 <算法笔记> 重点摘要:静态链表 1032 Sharing (25) 1052 Linked List ...
- PAT甲级 模拟题_C++题解
模拟题 PAT (Advanced Level) Practice 模拟题 目录 1008 Elevator (20) 1042 Shuffling Machine (20) 1046 Shortes ...
- 1080 Graduate Admission——PAT甲级真题
1080 Graduate Admission--PAT甲级练习题 It is said that in 2013, there were about 100 graduate schools rea ...
- PAT甲级 散列题_C++题解
散列 PAT (Advanced Level) Practice 散列题 目录 <算法笔记> 重点摘要 1002 A+B for Polynomials (25) 1009 Product ...
- PAT甲级 二叉树 相关题_C++题解
二叉树 PAT (Advanced Level) Practice 二叉树 相关题 目录 <算法笔记> 重点摘要 1020 Tree Traversals (25) 1086 Tree T ...
- PAT甲级 并查集 相关题_C++题解
并查集 PAT (Advanced Level) Practice 并查集 相关题 <算法笔记> 重点摘要 1034 Head of a Gang (30) 1107 Social Clu ...
- PAT甲级 Dijkstra 相关题_C++题解
Dijkstra PAT (Advanced Level) Practice Dijkstra 相关题 目录 <算法笔记>重点摘要 1003 Emergency (25) <算法笔记 ...
- PAT甲级 进制转换题_C++题解
进制转换题 PAT (Advanced Level) Practice 进制转换题 目录 <算法笔记> 重点摘要 1015 Reversible Primes (20) 1019 Gene ...
- PAT甲级 二叉查找树 相关题_C++题解
二叉查找树 PAT (Advanced Level) Practice 二叉查找树 相关题 目录 <算法笔记> 重点摘要 1099 Build A Binary Search Tree ( ...
随机推荐
- Selenium操作Chrome模拟手机浏览器
目录 使用指定设备 使用自定义设备 在使用Chrome浏览网页时,我们可以使用Chrome开发者工具模拟手机浏览器,在使用Selenium操作Chrome时同样也可以模拟手机浏览器.主要有以下两种用途 ...
- 【java反射】
反射之中包含了一个「反」字,所以想要解释反射就必须先从「正」开始解释. 一般情况下,我们使用某个类时必定知道它是什么类,是用来做什么的.于是我们直接对这个类进行实例化,之后使用这个类对象进行操作. A ...
- JavaScript DOM的一些扩展
对DOM的扩展主要是:Selectors API和HTML5. Selectors API Selectors API是由W3C发起指定的一个标准,致力于让浏览器原生支持CSS查询.Selectors ...
- numpy模块-渐入佳境
1.多维数组降为一维: numpy中的ravel().flatten().squeeze()的用法与区别 2. axis的理解 Python之NumPy(axis=0/1/2...)的透彻理解——通过 ...
- Deep & Cross Network总结
一.介绍 CTR预估全称是Click Through Rate,就是展示给用户的广告或者商品,估计用户点击的概率.公司规模较大的时候,CTR直接影响的价值在数十亿美元的级别.广告支付一个非常流行的模型 ...
- 如何从DOS命令窗口进行复制粘贴
在DOS窗口没有右键复制按钮,那我们如果想要进行复制粘贴该如何操作呢?本篇就来说明一下这个操作流程. 工具/原料 WIN7系统 方法/步骤 按“WIN+R”调出运行页面,在其中输入CMD然 ...
- 关于linux下的系统存储管理
https://blog.csdn.net/aaaaaab_/article/details/80159871 //查看当前系统磁盘使用空间 df -h //查看当前目录文件占用空间大小 du -sh ...
- 重置密码解决MySQL for Linux
重置密码解决MySQL for Linux错误 ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using passwor ...
- VM12_pro+Ubuntu16_64+Qt5.12.2环境搭建
1.准备软件[已经存网盘] 2.安装Vm 3.安装Ubuntu 4.进入linux,修改Qt安装包权限 5.运行Qt 6.第五步会弹出Qt安装的界面,默认安装就行了 7.修改环境变量 sudo ged ...
- iOS 字符串和图片互转
for (UIImage *myImg in _imgArray) { NSData *imageData = UIImageJPEGRepresentation(myImg,0.5); NSStri ...