【PAT甲级】1012 The Best Rank (25分)

解题过程的小记录,如有错误欢迎指出。

难度:二星(难点在排序的注意点

题目分析

给出一堆学生的三门课成绩,求出其个人平均成绩以及四种成绩各自排名的最优排名名次和科目,按照指定的查询顺序输出

注意点

同一门成绩的排序,两个并列第一后的名次是第三名(仔细分析给出样例可以发现题目对于同分的情况是这样处理的

我的解题过程

思路

将学生的各种信息设置成一个如下结构:

struct student {
	string ID;
	int C, M, E, A;//各门课成绩
	int noC, noM, noE, noA;//各门课排名
};

通过四个比较函数对学生的vector数组分别进行排序(其实可以简化成一个),然后按照排序完的顺序进行输出。

bug

  1. 因为内循环的下标写错导致不能输出想要的答案,不过这个通过和参考样例对比检查代码很快就debug出来了
  2. 刚开始没有考虑注意点内容即同分情况,出现了一个检测点报错。后来考虑了,咳咳,但考虑歪了,排名规则改成两个并列第一名后的是第二名,此时两个检测点报错。然后又卡了挺久,试了两个并列排名后的名次是第三名的规则才通过

代码

#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的代码

全部代码因版权原因不放出来,大家可以自行去柳神博客购买或者参考晴神的上机笔记~

借鉴点

  1. 如果没弄清平均分是向上取整还是向下取整或者是四舍五入的话,可以采用三门课算总分的方式来进行排序(机智啊~)
  2. 可以将分数存储在一个数组里,然后设置一个全局变量当下标参数,这样四个比较函数可以写成一个
  3. 成绩数组存储的时候可以就按照ACME的顺序存储可以简化程序逻辑
struct node {
 int id, best;
 int score[4], rank[4];
}stu[2005];
  1. 用一个exist[]数组来存放是否存在
for(int i = 0; i < n; i++) {
	 exist[stu[i].id] = i + 1;
 //有省略……
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值