解题过程的小记录,如有错误欢迎指出。
难度:二星(难点在排序的注意点
题目分析
给出一堆学生的三门课成绩,求出其个人平均成绩以及四种成绩各自排名的最优排名名次和科目,按照指定的查询顺序输出
注意点
同一门成绩的排序,两个并列第一后的名次是第三名(仔细分析给出样例可以发现题目对于同分的情况是这样处理的)
我的解题过程
思路
将学生的各种信息设置成一个如下结构:
struct student {
string ID;
int C, M, E, A;//各门课成绩
int noC, noM, noE, noA;//各门课排名
};
通过四个比较函数对学生的vector数组分别进行排序(其实可以简化成一个),然后按照排序完的顺序进行输出。
bug
- 因为内循环的下标写错导致不能输出想要的答案,不过这个通过和参考样例对比检查代码很快就debug出来了
- 刚开始没有考虑注意点内容即同分情况,出现了一个检测点报错。后来考虑了,咳咳,但考虑歪了,排名规则改成两个并列第一名后的是第二名,此时两个检测点报错。然后又卡了挺久,试了两个并列排名后的名次是第三名的规则才通过
代码
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
struct student {
string ID;
int C, M, E, A;//各门课成绩
int noC, noM, noE, noA;//各门课排名
};
int Ccomp(const student s1, const student s2) {
return s1.C > s2.C;
}
int Mcomp(const student s1, const student s2) {
return s1.M > s2.M;
}
int Ecomp(const student s1, const student s2) {
return s1.E > s2.E;
}
int Acomp(const student s1, const student s2) {
return s1.A > s2.A;
}
void bestRank(student s) {
if (s.noA <= min(min(s.noC, s.noE), s.noM)) cout << s.noA << " A" << endl;
else if (s.noC <= min(min(s.noA, s.noE), s.noM)) cout << s.noC << " C" << endl;
else if (s.noM <= min(min(s.noA, s.noC), s.noE)) cout << s.noM << " M" << endl;
else cout << s.noE << " E" << endl;
}
int main()
{
//输入数据
int N, M;
cin >> N >> M;
vector<student> students(N);
vector<string> query(M);
for (int i = 0; i < N; i++) {//成绩的输入
cin >> students[i].ID >> students[i].C >> students[i].M >> students[i].E;
students[i].A = (students[i].C + students[i].M + students[i].E) / 3;//在输入途中顺便把平均分算了
}
for (int i = 0; i < M; i++) {//查询顺序的输入
cin >> query[i];
}
//开始进行各门课的排序并输出
sort(students.begin(), students.end(), Ccomp);
students[0].noC = 1;//经排序后最开始的肯定是第一名
for (int i = 1; i < N; i++) {
if (students[i].C == students[i - 1].C) students[i].noC = students[i - 1].noC;
else students[i].noC = i + 1;//******究极易错点:两个并列第一名后面的是第三名(这谁能想得到啊嘤嘤嘤
}
sort(students.begin(), students.end(), Mcomp);
students[0].noM = 1;
for (int i = 0; i < N; i++) {
if (students[i].M == students[i - 1].M) students[i].noM = students[i - 1].noM;
else students[i].noM = i + 1;
}
sort(students.begin(), students.end(), Ecomp);
students[0].noE = 1;
for (int i = 0; i < N; i++) {
if (students[i].E == students[i - 1].E) students[i].noE = students[i - 1].noE;
else students[i].noE = i + 1;
}
sort(students.begin(), students.end(), Acomp);
students[0].noA = 1;
for (int i = 0; i < N; i++) {
if (students[i].A == students[i - 1].A) students[i].noA = students[i - 1].noA;
else students[i].noA = i + 1;
}
for (int i = 0; i < M; i++) {
int j = 0;
for (j; j < N; j++) {
if (query[i] == students[j].ID) {
bestRank(students[j]);//********这里没看清写错成students[i]了
break;
}
}
if (j == N) cout << "N/A" << endl;
}
return 0;
}
dalao的代码
全部代码因版权原因不放出来,大家可以自行去柳神博客购买或者参考晴神的上机笔记~
借鉴点
- 如果没弄清平均分是向上取整还是向下取整或者是四舍五入的话,可以采用三门课算总分的方式来进行排序(机智啊~)
- 可以将分数存储在一个数组里,然后设置一个全局变量当下标参数,这样四个比较函数可以写成一个
- 成绩数组存储的时候可以就按照ACME的顺序存储可以简化程序逻辑
struct node {
int id, best;
int score[4], rank[4];
}stu[2005];
- 用一个exist[]数组来存放是否存在
for(int i = 0; i < n; i++) {
exist[stu[i].id] = i + 1;
//有省略……
}