PAT (Advanced Level) Practice 1012 The Best Rank

一、概述

给出N个学生的各科成绩,输出该学生的单科最好成绩。

我使用了多次sort实现。坑点在于三个学生的分数若为80,80,90,则名次应该是1,2,2,而不是1,2,3.选择后者测试点1和2过不去。

二、分析

既然要输入最好成绩,那么便需要根据每门成绩排序一次,共排序四次。因此我使用结构存储学生的ID,各科成绩和各科排名。如下:

struct Student
{
	char ID[6];
	int C, M, E, A;
	int rank[4];
}student[2000];

注意rank数组是用于存储单科成绩的,因为当成绩相同时,各科优先级顺序为A,C,M,E,那么rank数组也按这个顺序,这样一来,在最后选择rank数组的最小值时,自动保存最前面的最小值。也就自动按照优先级排序了。

排序四次,因此需要四个cmp函数,如下:

bool cmpC(Student a, Student b)
{
	return a.C > b.C;
}
bool cmpM(Student a, Student b)
{
	return a.M > b.M;
}
bool cmpE(Student a, Student b)
{
	return a.E > b.E;
}
bool cmpA(Student a, Student b)
{
	return a.A > b.A;
}

四个sort函数如下:

sort(student, student + N, cmpA);
	for (i = 0; i < N; i++)
	{
		if (i > 0)
		{
			if (student[i].A == student[i - 1].A)
				student[i].rank[0] = student[i - 1].rank[0];
			else
				student[i].rank[0] = i;
		}
		else
			student[i].rank[0] = i;
	}
	sort(student, student + N, cmpC);
	for (i = 0; i < N; i++)
	{
		if (i > 0)
		{
			if (student[i].C == student[i - 1].C)
				student[i].rank[1] = student[i - 1].rank[1];
			else
				student[i].rank[1] = i;
		}
		else
			student[i].rank[1] = i;
	}
	sort(student, student + N, cmpM);
	for (i = 0; i < N; i++)
	{
		if (i > 0)
		{
			if (student[i].M == student[i - 1].M)
				student[i].rank[2] = student[i - 1].rank[2];
			else
				student[i].rank[2] = i;
		}
		else
			student[i].rank[2] = i;
	}
	sort(student, student + N, cmpE);
	for (i = 0; i < N; i++)
	{
		if (i > 0)
		{
			if (student[i].E == student[i - 1].E)
				student[i].rank[3] = student[i - 1].rank[3];
			else
				student[i].rank[3] = i;
		}
		else
			student[i].rank[3] = i;
	}

sort下面的四个循环用于存储对应名次,在名次相同时的处理一定要注意。

接下来对照输入选择对应的学生的rank中的最小值输出即可,这可真绕。

我使用char存的ID,因此使用strcmp函数,注意vs2015使用string头文件即可,但是oj要求使用cstring。

另外,由于只要求比较平均数的大小而不要求输出平均数,为了避免四舍五入的麻烦,直接比较和就可以,而不用再除以三。

这是题目出的不严谨的一个地方。

三、总结

对于sort和cmp应用很好的一道题。

PS:代码如下:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

struct Student
{
	char ID[6];
	int C, M, E, A;
	int rank[4];
}student[2000];

bool cmpC(Student a, Student b)
{
	return a.C > b.C;
}
bool cmpM(Student a, Student b)
{
	return a.M > b.M;
}
bool cmpE(Student a, Student b)
{
	return a.E > b.E;
}
bool cmpA(Student a, Student b)
{
	return a.A > b.A;
}

int main()
{
	int N, M;
	scanf("%d %d", &N, &M);
	int i;
	for (i = 0; i < N; i++)
	{
		scanf("%s %d %d %d", &student[i].ID, &student[i].C, &student[i].M, &student[i].E);
		student[i].A = student[i].C + student[i].M + student[i].E;
	}
	sort(student, student + N, cmpA);
	for (i = 0; i < N; i++)
	{
		if (i > 0)
		{
			if (student[i].A == student[i - 1].A)
				student[i].rank[0] = student[i - 1].rank[0];
			else
				student[i].rank[0] = i;
		}
		else
			student[i].rank[0] = i;
	}
	sort(student, student + N, cmpC);
	for (i = 0; i < N; i++)
	{
		if (i > 0)
		{
			if (student[i].C == student[i - 1].C)
				student[i].rank[1] = student[i - 1].rank[1];
			else
				student[i].rank[1] = i;
		}
		else
			student[i].rank[1] = i;
	}
	sort(student, student + N, cmpM);
	for (i = 0; i < N; i++)
	{
		if (i > 0)
		{
			if (student[i].M == student[i - 1].M)
				student[i].rank[2] = student[i - 1].rank[2];
			else
				student[i].rank[2] = i;
		}
		else
			student[i].rank[2] = i;
	}
	sort(student, student + N, cmpE);
	for (i = 0; i < N; i++)
	{
		if (i > 0)
		{
			if (student[i].E == student[i - 1].E)
				student[i].rank[3] = student[i - 1].rank[3];
			else
				student[i].rank[3] = i;
		}
		else
			student[i].rank[3] = i;
	}
	int j, k;
	for (i = 0; i < M; i++)
	{
		char _ID[6];
		scanf("%s", &_ID);
		int TOF = 0;
		for (j = 0; j < N; j++)
		{
			if (strcmp(_ID, student[j].ID) == 0)
			{
				TOF = 1;
				int min = 2000;
				int sub = -1;
				for (k = 0; k < 4; k++)
				{
					if (student[j].rank[k] < min)
					{
						min = student[j].rank[k];
						sub = k;
					}
				}
				switch (sub)
				{
				case 0:
					printf("%d A\n", min+1);
					break;
				case 1:
					printf("%d C\n", min+1);
					break;
				case 2:
					printf("%d M\n", min+1);
					break;
				case 3:
					printf("%d E\n", min+1);
					break;	
				}
			}
		}
		if (TOF == 0)
			printf("N/A\n");
	}
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值