洛谷 B3968 [GESP202403 五级] 成绩排序 题解

讲解

由于一个学生包含语文、数学、英语三科的成绩,所以我们可以先定义一个结构体,在里面存储语文分数、数学分数、英语分数、总分、语文与数学的总分、语文与数学的最高分、排名和原始位置,结构体代码如下:

struct score{
	int c,m,e/*语数英的成绩*/,total/*总分*/,cm/*语文与数学的总分*/,max_cm/*语文与数学的最高分*/,num/*初始位置*/,ranking/*排名*/;
}sco[10000];

随后,我们就要进行输入及初始化,这个肯定不用讲,大家都会。代码如下:

for(int i=0;i<n;++i) {
	cin>>sco[i].c>>sco[i].m>>sco[i].e;//输入
	sco[i].total=sco[i].c+sco[i].m+sco[i].e;//总分
	sco[i].cm=sco[i].c+sco[i].m;//语文数学总分
	sco[i].max_cm=max(sco[i].c,sco[i].m);//语文数学最高分
	sco[i].num=i;//初始位置
}

然后,我们就用 sort 函数对其按照题目中给定的方式进行排序。而由于是结构体排序,要写一个规则,如下:

bool cmp1(score a,score b) {
	if(a.total!=b.total) return a.total>b.total;//比较总分
	else if(a.cm!=b.cm) return a.cm>b.cm;//比较语文和数学的总分
	else if(a.max_cm!=b.max_cm) return a.max_cm>b.max_cm;//比较语文和数学的最高分
	return true;//都一样则并列
}

在排了序之后我们就可以开始记录排名了。为什么要记录排名呢?因为输出时需要按初始顺序依次输出每个学生的排名,这也就意味着又要将其按初始位置再排序一遍,如果不记录排名的话,等到输出时你还是不知道这个学生的排名。需要注意的是,总分、语文数学成绩和以及语文数学最高分全部一样的学生排名是一样的,所以每次还要判断当前学生的总分、语文数学成绩和以及语文数学最高分是否与上一个学生总分、语文数学成绩和以及语文数学最高分相同,如果相同,该学生的排名就要改成上一个学生的排名。代码如下:

for(int i=0;i<n;++i) {
 	sco[i].ranking=i+1;//记录排名
	if(i!=0) if(sco[i].total==sco[i-1].total&&sco[i].cm==sco[i-1].cm&&sco[i].max_cm==sco[i-1].max_cm) sco[i].ranking=sco[i-1].ranking;//如果相同就更改排名
}

最后,由于输出要按初始顺序输出,所以还要按初始顺序再进行一遍排序。同样由于是结构体,所以要自己写规则,如下:

bool cmp2(score a,score b) {
	return a.num<b.num;//从小到大
}

最后只要输出就行啦!代码如下:

for(int i=0;i<n;++i) cout<<sco[i].ranking<<"\n";

code

为了方便你们抄代码我就不加注释了。

#include<iostream>
#include<algorithm>
using namespace std;
struct score{
	int c,m,e,total,cm,max_cm,num,ranking;
}sco[10000];
bool cmp1(score a,score b) {
	if(a.total!=b.total) return a.total>b.total;
	else if(a.cm!=b.cm) return a.cm>b.cm;
	else if(a.max_cm!=b.max_cm) return a.max_cm>b.max_cm;
	return true;
}
bool cmp2(score a,score b) {
	return a.num<b.num;
}
int main() {
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	int n;
	cin>>n;
	for(int i=0;i<n;++i) {
	cin>>sco[i].c>>sco[i].m>>sco[i].e;
	sco[i].total=sco[i].c+sco[i].m+sco[i].e;
	sco[i].cm=sco[i].c+sco[i].m;
	sco[i].max_cm=max(sco[i].c,sco[i].m);
	sco[i].num=i;
}
	sort(sco,sco+n,cmp1);
	for(int i=0;i<n;++i) {
		sco[i].ranking=i+1;
		if(i!=0) if(sco[i].c==sco[i-1].c&&sco[i].m==sco[i-1].m&&sco[i].e==sco[i-1].e) sco[i].ranking=sco[i-1].ranking;
	}
	sort(sco,sco+n,cmp2);
	for(int i=0;i<n;++i) cout<<sco[i].ranking<<"\n";
	return 0;
}
  • 13
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值