1012 The Best Rank (25分)
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), and E - 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, E and A - 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
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, M and E. 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
Sample Output:
1 C
1 M
1 E
1 A
3 A
N/A
这道题就是让我们录入学生的ID、三门课成绩,算出平均成绩,当成第四门课,然后每门课进行排名,最后按A>C>M>E的同排名优先级选出查询成绩的同学排名最好的一门课,输出排名数以及科目代号,当然咯,如果搜索不到,那就输出N/A
Attention:
- 排序要求:同分者排名需要相同,例如会出现 :1,2,2,4这种并列第二的情况,这时,第二和第三个同学排名需要一样
- 搜索实现:可以用vector结合find_if然后再配合仿函数使用,详见文末链接,我已经整理好vector搜索的几种实现方式
Details:
虽然不知道题目里有没有坑,但是为了保证精度,我在算平均值的时候并没有除3,而是直接存了三门功课的总和。
原本学生ID我是用字符数组来存的,只可惜后来在输入需要查询的学生学号时,尽管我每次便利都创建新的对象加进vector中,但vector中所有变量仍然如同只创建了一个变量一样是同一个值,搜索了一下,发现还真有个哥们和我出现同样的问题:* * * link * * *,不过他在改成string之后就解决了问题,于是我也修改了一下,如果大家知道问题所在,可以评论告诉我
至于排序问题,首先用sort函数排序好,然后遍历给rank数组进行赋值,只不过在进行赋值的时候并不单纯的赋为索引号+1,而是要和前一个对象的分数进行一个比较,如果相同,那么排名就赋为前一个对象的排名值。
Code:
#include <bits/stdc++.h>
#define M 0x3f3f3f3f
using namespace std;
typedef struct{
string id;
int score[4];
int rank[4]={-1};
}stuInfo;
vector<stuInfo> info;
bool cmpC(stuInfo a, stuInfo b){ return (a.score[1]>b.score[1]);}
bool cmpM(stuInfo a, stuInfo b){ return (a.score[2]>b.score[2]);}
bool cmpE(stuInfo a, stuInfo b){ return (a.score[3]>b.score[3]);}
bool cmpA(stuInfo a, stuInfo b){ return (a.score[0]>b.score[0]);}
typedef struct ifIdMatch{
string m_id;
ifIdMatch(string id):m_id(id){}
bool operator()(const stuInfo& si){
return (si.id.compare(m_id)==0);
}
}ifIdMatch;
void Rank(stuInfo si){
int min=M;
char map[4]={'A','C','M','E'};
int flag=-1;
for(int i=0;i<4;i++){
if(min>si.rank[i]){
min=si.rank[i];
flag=i;
}
}
cout<<min<<" "<<map[flag];
}
int main(){
int n,m;
cin>>n>>m;
for(int i=0;i<n;i++){
stuInfo si;
cin>>si.id>>si.score[1]>>si.score[2]>>si.score[3];
si.score[0]=si.score[1]+si.score[2]+si.score[3];
info.push_back(si);
}
sort(info.begin(),info.end(),cmpC);
for(int i=0;i<n;i++) if(i>0&&info[i-1].score[1]==info[i].score[1]) info[i].rank[1]=info[i-1].rank[1];else info[i].rank[1]=i+1;
sort(info.begin(),info.end(),cmpM);
for(int i=0;i<n;i++) if(i>0&&info[i-1].score[2]==info[i].score[2]) info[i].rank[2]=info[i-1].rank[2];else info[i].rank[2]=i+1;
sort(info.begin(),info.end(),cmpE);
for(int i=0;i<n;i++) if(i>0&&info[i-1].score[3]==info[i].score[3]) info[i].rank[3]=info[i-1].rank[3];else info[i].rank[3]=i+1;
sort(info.begin(),info.end(),cmpA);
for(int i=0;i<n;i++) if(i>0&&info[i-1].score[0]==info[i].score[0]) info[i].rank[0]=info[i-1].rank[0];else info[i].rank[0]=i+1;
vector<string> idVec;
for(int i=0;i<m;i++){
string id;
cin>>id;
idVec.push_back(id);
}
for(int i=0;i<m;i++){
std::vector<stuInfo>::iterator it = find_if(info.begin(),info.end(),ifIdMatch(idVec[i]));
if(it!=info.end())
Rank(*it);
else cout<<"N/A";
if(i<m-1) cout<<endl;
}
return 0;
}
Summary and harvest
(for my current level)
- 细说 类/结构体+vector+find()/find_if() 实现自定义查询 C++ STL(要了解搜索时find_if()函数怎么和仿函数配合使用)
函数原型:
返回值:vector迭代器 find_if(迭代起点,迭代终点,一元函数);
std::vector< STRUCT >::iterator it = find_if(vec.begin(),vec.end(),COMP_FUNCTION);
如果要比较的对象是两个string,则利用函数compare()。若要比较string s1和s2则写为:s1.compare(s2),若返回值为0,则两者相等。