每日一道算法题 Day11 of PAT 1012 The Best Rank (25分) 详解

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_if(迭代起点,迭代终点,一元函数);
std::vector< STRUCT >::iterator it = find_if(vec.begin(),vec.end(),COMP_FUNCTION);

如果要比较的对象是两个string,则利用函数compare()。若要比较string s1和s2则写为:s1.compare(s2),若返回值为0,则两者相等。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值