重复代码很多的一道模拟题,感觉写得不够好。
坑点就是,可能会忘记分数相等时,排名是并列的,取高。至于课程的优先级问题,把高优先级的课程放在低优先级之后排序即可,如果排名相等,高优先级会覆盖掉低优先级。
然后,最后针对 m 个 id,输出最高排名。如果用线性扫描,复杂度 O(nm),也不会超时。可以考虑对 id 排序,然后二分,我就懒得写了。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e3+3;
const double EPS = 1e-6;
char course[4] = {'A', 'C', 'M', 'E'};
struct Student {
string id;
double mark[4];
int bestRank;
char bestCourse;
Student() {
bestRank = maxn;
}
void getInfo() {
cin >> id >> mark[1] >> mark[2] >> mark[3];
}
void getAve() {
mark[0] = (mark[1] + mark[2] + mark[3]) / 3.0;
}
} students[maxn];
int n, m;
void read() {
cin >> n >> m;
for (int i = 1; i <= n; ++i) {
students[i].getInfo();
students[i].getAve();
}
}
bool cmpA(const Student& s1, const Student& s2) {
return s1.mark[0] - s2.mark[0] > EPS;
}
bool cmpC(const Student& s1, const Student& s2) {
return s1.mark[1] - s2.mark[1] > EPS;
}
bool cmpM(const Student& s1, const Student& s2) {
return s1.mark[2] - s2.mark[2] > EPS;
}
bool cmpE(const Student& s1, const Student& s2) {
return s1.mark[3] - s2.mark[3] > EPS;
}
void getBestRank(int c) {
int high = maxn;
for (int i = 1; i <= n; ++i) {
// 分数有可能相同,排名并列;考虑到精度,直接用==就行(逃
if (students[i-1].mark[c] == students[i].mark[c]) {
high = min(high, i-1);
} else {
high = i;
}
if (students[i].bestRank >= high) {
students[i].bestRank = high;
students[i].bestCourse = course[c];
}
}
}
void solve() {
sort(students+1, students+1+n, cmpE);
getBestRank(3);
sort(students+1, students+1+n, cmpM);
getBestRank(2);
sort(students+1, students+1+n, cmpC);
getBestRank(1);
sort(students+1, students+1+n, cmpA);
getBestRank(0);
string id;
while (m--) {
cin >> id;
bool isExist = false;
for (int i = 1; i <= n; ++i) {
if (students[i].id == id) {
cout << students[i].bestRank << " " << students[i].bestCourse << endl;
isExist = true;
break;
}
}
if (!isExist) {
cout << "N/A" << endl;
}
}
}
int main() {
read();
solve();
return 0;
}