PAT (Advanced Level) Practice 1012 The Best Rank

本文介绍了一种算法,用于找出学生在多个科目中的最佳成绩排名。通过定义结构体存储学生信息,包括ID、各科成绩及排名,利用C++中的sort函数和自定义比较函数cmp,对每个科目进行独立排序,确保相同成绩的学生排名正确。最终,根据输入的学生ID,输出其单科最好成绩及其科目。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概述

给出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");
	}
}

 

### 关于PAT Basic Level Practice测试点及题目解析 #### 题目难度分级 PAT(Programming Ability Test)是由浙江大学举办的计算机程序设计能力考试,分为不同级别。其中乙级即Basic Level主要面向初学者,考察基本编程技能[^1]。 #### 测试点特点 对于PAT Basic Level中的某些特定题目而言,其测试点设置较为严格。例如,在处理字符串匹配类问题时,需要注意算法逻辑中何时应当终止循环以防止不必要的重复计算;而在涉及数值运算的问题里,则可能因为边界条件而增加复杂度[^3]。 #### 编程语言的选择影响 值得注意的是,尽管大部分简单题目可以作为学习某种新语言的良好实践材料,但在实际操作过程中可能会遇到由于所选语言特性而导致难以通过全部测试点的情况。比如Java在面对部分效率敏感型试题时表现不佳,这可能是由于该语言本身的执行速度相对较慢以及内存管理方式等因素造成的。因此有时不得不转而采用其他更适合解决此类问题的语言版本来完成解答[^2]。 ```cpp #include<bits/stdc++.h> using namespace std; int a[100000]; int c=1; void getPrime(){ int flag=0; for(int i=2;i<105000;i++){ flag=1; for(int j=2;j<=sqrt(i);j++){ if(i%j==0){ flag=0; break; } } if(flag==1) a[c++]=i; } } int main(){ int m,n,i,t=1; scanf("%d %d",&m,&n); getPrime(); for(i=m;i<=n;i++){ if(t%10==1){ printf("%d",a[i]); t++; }else{ printf(" %d",a[i]); t++; } if((t-1)%10==0) printf("\n"); } return 0; } ``` 上述C++代码展示了如何实现一个简单的质数打印功能,并且针对输出格式进行了特殊处理以满足特定要求。这段代码很好地体现了编写高效解决方案的重要性,尤其是在应对像PAT这样的在线评测系统时[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值