✍个人博客:https://blog.csdn.net/Newin2020?spm=1011.2415.3001.5343
📚专栏地址:PAT题解集合
📝原题地址:题目详情 - 1012 The Best Rank (pintia.cn)
🔑中文翻译:最佳排名
📣专栏定位:为想考甲级PAT的小伙伴整理常考算法题解,祝大家都能取得满分!
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪
To evaluate the performance of our first year CS majored students, we consider their grades of three courses only:
C- C Programming Language,M- Mathematics (Calculus or Linear Algrbra), andE- English. At the mean time, we encourage students by emphasizing on their best ranks – that is, among the four ranks with respect to the three courses and the average grade, we print the best rank for each student.For example, The grades of
C,M,EandA- Average of 4 students are given as the following:StudentID C M E A 310101 98 85 88 90 310102 70 95 88 84 310103 82 87 94 88 310104 91 91 91 91
- 1
- 2
- 3
- 4
- 5
Then the best ranks for all the students are No.1 since the 1st one has done the best in C Programming Language, while the 2nd one in Mathematics, the 3rd one in English, and the last one in average.
Input Specification:
Each input file contains one test case. Each case starts with a line containing 2 numbers N and M (≤2000), which are the total number of students, and the number of students who would check their ranks, respectively. Then N lines follow, each contains a student ID which is a string of 6 digits, followed by the three integer grades (in the range of [0, 100]) of that student in the order of
C,MandE. Then there are M lines, each containing a student ID.Output Specification:
For each of the M students, print in one line the best rank for him/her, and the symbol of the corresponding rank, separated by a space.
The priorities of the ranking methods are ordered as
A>C>M>E. Hence if there are two or more ways for a student to obtain the same best rank, output the one with the highest priority.If a student is not on the grading list, simply output
N/A.Sample Input:
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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
Sample Output:
1 C 1 M 1 E 1 A 3 A N/A
- 1
- 2
- 3
- 4
- 5
- 6
我们只考虑他们的三门成绩:C–c语言,M–数学,E–英语,除此之外,我们还会考虑 A –三门成绩平均值。
注意: 平均成绩为三科成绩平均值四舍五入取整的结果。
我们要输出每个学生四门成绩中排名最高的那一科,如果遇到排名相同的,则按照 A > C > M > E A > C > M > E A>C>M>E 规则输出他的最佳排名。
如果无法查询到该学生的成绩,则输出 N/A。
首先,我们用到了两个容器对学生的信息进行存储。一个是哈希表 grades ,能够通过学生的 id 快速查找到其对应的成绩。另一个是二维数组 q ,从 0~4 层数组分别存储 ACME 的成绩。
对 q 中的四层数组进行排序,这样就得到了每一科目包括平均值从小到大的排序。
开始查找对应学生的最佳科目排名,我们这里采用的是二分查找法,因为 q 中已经是有序的了,所以可以二分找到对应的排名。
这里需要注意的是由于数组中是从小到大进行排序的,所以下标越大分数越高,但是我们输出的顺序是反过来的,排名序号越小代表分数越高。所以这里的二分查找需要找到分数的右边界,然后再用 g.szie() 减去它就是最终的排名。
例如,86,88,88,90,91 这五个成绩,我们要查找的是 88 ,而 88 有两个,二分查找需要找到 88 的右边界即上面例子中下标为 2 的数字(下标从 0 开始),然后再用 g.szie() 减去它得到 5 - 2 = 3 ,也就是排名第 3 ,正好符合想要的结果。
最后要输出结果,字符 ACME 可以用一个数组存起来,方便调用。另外,如果在哈希表找不到给定 id 需要输出 N/A 。
#include
using namespace std;
unordered_map<string, vector<int>> grades;
vector<int> q[4]; //q[0]:A,q[1]:C,q[2]:M,q[3]:E
//二分获取排名
int get_rank(vector<int> g, int x)
{
int l = 0, r = g.size() - 1;
while (l < r)
{
int mid = (l + r + 1) >> 1;
if (g[mid] <= x) l = mid;
else r = mid - 1;
}
return g.size() - r;
}
int main()
{
int n, m;
cin >> n >> m;
//输入学生信息
for (int i = 0; i < n; i++)
{
string id;
int t[4] = { 0 };
cin >> id;
for (int j = 1; j < 4; j++)
{
cin >> t[j];
t[0] += t[j];
}
t[0] = round(t[0] / 3.0); //求平均值(四舍五入)
for (int j = 0; j < 4; j++)
{
grades[id].push_back(t[j]);
q[j].push_back(t[j]);
}
}
//对成绩进行排序
for (int i = 0; i < 4; i++) sort(q[i].begin(), q[i].end());
//查找学生成绩排名
char names[4] = { 'A','C','M','E' };
while (m--)
{
string id;
cin >> id;
//判断id是否存在
if (!grades.count(id)) puts("N/A");
else
{
char c;
int minv = 1e9;
for (int i = 0; i < 4; i++)
{
int rank = get_rank(q[i], grades[id][i]);
//排名相等情况下,A>C>M>E
if (rank < minv)
{
minv = rank;
c = names[i];
}
}
cout << minv << " " << c << endl;
}
}
return 0;
}