当前位置: 首页 > news >正文

PAT 甲级题目讲解:1012《The Best Rank》

✅ PAT 甲级题目讲解:1012《The Best Rank》

🧩 题目简介

本题要求根据每位学生的三门课程成绩(C, M, E)以及平均成绩 A,为每个指定学号输出其最佳排名和对应科目标识(A/C/M/E)。

若该学号不存在,则输出 N/A


🧪 样例分析

输入样例:

5 6
310101 98 85 88
310102 70 95 88
310103 82 87 94
310104 91 91 91
310105 85 90 90
310101
310102
310103
310104
310105
999999
  • 第一行 5 6 表示有 5 个学生,6 次查询;
  • 接下来的 5 行每行一个学生,格式为:学号 C M E;
  • 每名学生的平均成绩 A = (C + M + E) / 3.0
  • 要对所有学生在 A/C/M/E 四门科目分别排名;
  • 查询每个学号时输出该生在四科中排名最靠前的名次及对应科目
  • 若学号不存在(如 999999),输出 N/A

输出:

1 A
1 C
1 E
1 A
3 A
N/A

解释:

  • 310101 平均分最高(90.3),A 科第一;
  • 310102 C 科最高(95),排名第一;
  • 310103 E 分最高(94),E 科第一;
  • 310104 所有分数都是 91,总评也第一,A 科优先;
  • 310105 各科均非第一,但平均排名第三;
  • 999999 不存在,输出 N/A

🔍 解题思路

本题考察多字段排序、排名处理与查询映射

📎 变量说明表格

变量名类型含义
n, mint学生数量、查询次数
b[]int[]学号 → 数组下标的映射表(-1 表示不存在)
s[]Stu[]学生信息结构体数组
rkint当前学生的最优排名
cschar当前学生的最优科目(A/C/M/E)

✅ Step 1:定义结构体与成绩处理

每个学生有三门成绩以及平均成绩,结构体定义如下:

struct Stu {int id, c, m, e;double a;int rk;char cs;
};

读入数据时同时计算平均成绩 A,并将最优排名初始化为极大值:

cin >> s[i].id >> s[i].c >> s[i].m >> s[i].e;
s[i].a = (s[i].c + s[i].m + s[i].e) / 3.0;
s[i].rk = 1e9;

✅ Step 2:通用排名处理函数设计

为避免对 A/C/M/E 四科重复排序逻辑,我们设计一个通用函数:

void process_rank(Stu s[], int n, char course,bool (*cmp)(Stu, Stu), double (*getScore)(Stu)) {sort(s + 1, s + 1 + n, cmp);int rank = 1;for (int i = 1; i <= n; i++) {if (i > 1 && getScore(s[i]) != getScore(s[i - 1]))rank = i;if (rank < s[i].rk) {s[i].rk = rank;s[i].cs = course;}}
}
✏️ 参数说明:
  • cmp:排序比较函数,例如 cmpa() 按平均成绩排序;
  • getScore:获取对应科目成绩的函数,如 getA() 返回 s.a
  • course:当前处理科目名(A/C/M/E);

这样我们只需定义好各科比较与提取函数:

bool cmpa(Stu x, Stu y) { return x.a > y.a; }
double getA(Stu s) { return s.a; }
// 同理定义 cmpc/getC, cmpm/getM, cmpe/getE

调用统一处理四科排序并更新最优排名:

process_rank(s, n, 'A', cmpa, getA);
process_rank(s, n, 'C', cmpc, getC);
process_rank(s, n, 'M', cmpm, getM);
process_rank(s, n, 'E', cmpe, getE);

✅ Step 3:建立映射并处理查询

为实现 O(1) 查询学号信息,我们用数组记录每个学生编号出现的下标:

b[s[i].id] = i; // 记录学号对应下标

处理查询时直接查表输出:

if (b[x] == -1)cout << "N/A";
elsecout << s[b[x]].rk << " " << s[b[x]].cs;

✅ 完整代码(C++)

#include <bits/stdc++.h>
using namespace std;int n, m, b[1000005];struct Stu {int id, c, m, e;double a;int rk;char cs;
} s[2005];bool cmpa(Stu x, Stu y) { return x.a > y.a; }
bool cmpc(Stu x, Stu y) { return x.c > y.c; }
bool cmpm(Stu x, Stu y) { return x.m > y.m; }
bool cmpe(Stu x, Stu y) { return x.e > y.e; }double getA(Stu s) { return s.a; }
double getC(Stu s) { return s.c; }
double getM(Stu s) { return s.m; }
double getE(Stu s) { return s.e; }void process_rank(Stu s[], int n, char course,bool (*cmp)(Stu, Stu), double (*getScore)(Stu)) {sort(s + 1, s + 1 + n, cmp);int rank = 1;for (int i = 1; i <= n; i++) {if (i > 1 && getScore(s[i]) != getScore(s[i - 1]))rank = i;if (rank < s[i].rk) {s[i].rk = rank;s[i].cs = course;}}
}int main() {cin >> n >> m;memset(b, -1, sizeof(b));for (int i = 1; i <= n; i++) {cin >> s[i].id >> s[i].c >> s[i].m >> s[i].e;s[i].a = (s[i].c + s[i].m + s[i].e) / 3.0;s[i].rk = 1e9;}process_rank(s, n, 'A', cmpa, getA);process_rank(s, n, 'C', cmpc, getC);process_rank(s, n, 'M', cmpm, getM);process_rank(s, n, 'E', cmpe, getE);for (int i = 1; i <= n; i++)b[s[i].id] = i;while (m--) {int x;cin >> x;if (b[x] == -1) {cout << "N/A";} else {cout << s[b[x]].rk << " " << s[b[x]].cs;}if(m) cout << "\n";}return 0;
}

🚧 常见错误提醒

错误类型具体表现
并列排名未处理相同分数未维持同一名次
忘记更新最优科目排名更新时未赋值 cs
未初始化 rk忘记设为极大值可能导致排名错乱
查询学号不存在未判断b[x] == -1 判断缺失,输出错误

✅ 总结归纳

  • 核心:多字段排名 + 最优解取值
  • 统一封装函数提升复用性与可维护性;
  • 查询用数组或哈希表快速定位。

📊 复杂度分析

  • 时间复杂度
    • 排序次数:4 次,每次 O(nlog⁡n)\mathcal{O}(n \log n)O(nlogn)
    • 查询次数:mmm 次,每次 O(1)\mathcal{O}(1)O(1)
    • 总复杂度:

O(nlog⁡n+m) \mathcal{O}(n \log n + m) O(nlogn+m)

  • 空间复杂度

    主要来源于学生数据与映射数组,约为:

O(n+106) \mathcal{O}(n + 10^6) O(n+106)


🧠 思维拓展

  • 如果课程增多,如何更灵活地支持动态排序?
  • 能否使用 map<int, Stu> 实现学号查找替代数组?
  • 支持查询所有科目的排名并排序输出,该如何扩展?
http://www.dtcms.com/a/313468.html

相关文章:

  • 【硬件-笔试面试题】硬件/电子工程师,笔试面试题-55,(知识点:STM32,外设及其特点)
  • 力扣-124.二叉树中的最大路径和
  • LLM调研
  • 计算用户日活:从数据设计到可视化的全流程(高频场景题)
  • 秋招笔记-8.3
  • AUTOSAR进阶图解==>AUTOSAR_RS_SystemTemplate
  • 元宇宙三维化会给游戏行业带来哪些改变?
  • 什么是列存储(Columnar Storage)?深度解析其原理与应用场景
  • 常见的深度学习模块/操作中的维度约定(系统性总结)
  • io_cancel系统调用及示例
  • e2studio开发RA4M2(6)----GPIO外部中断(IRQ)配置
  • 算法题(181):最大直方矩形面积
  • datasets库 的map方法num_proc=16并行踩坑
  • Java 中的 final 关键字有哪些用法?
  • C++ 虚函数相关问题 **
  • 基于云模型的模糊综合风险评估Matlab代码
  • 网关与路由器的区别
  • access系统调用及示例
  • 延迟任务方案-DelayQueue
  • SpringBoot 2.x 升 3.x 避坑指南:企业级项目的实战问题与解决方案
  • Celery-分布式任务队列
  • MySQL深度理解-MySQL锁机制
  • 数据结构学习(day01)
  • 第八章:进入Redis的SET的核心
  • Android系统模块编译调试与Ninja使用指南
  • 【数据分享】各省粮食外贸依存度、粮食波动率等粮食相关数据合集(2011-2022)(获取方式看文末)
  • 【MATLAB】(六)多项式的创建与四则运算
  • python的高校奖助学金系统
  • 23 Active Directory攻击与防护策略解析
  • 编译旧版本的electron内核