PAT A1012 The Best Rank (25分)

题意:给三个分数CME,加上算出来的平均分(要四舍五入,测试了才发现的),4个分数对应有4个排名,给出他们的最好排名(聊以自慰嘛→_→),最后根据给出的查询编号,查询出他们的最好排名和对应学科,或者查无此人。

AC代码:

//1012 The Best Rank (25分) https://pintia.cn/problem-sets/994805342720868352/problems/994805502658068480
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
struct student {
	char id[7];
	int score[4];
	int rank[4];
	int best;//最好排名
	int best_id;//最好排名对应科目ACME
}s[2020];
char id[2020][7] = { 0 };
char sub[5] = "ACME";
bool cmp_c(student s1, student s2)
{
	if (s1.score[1] != s2.score[1]) return s1.score[1] > s2.score[1];
	else return strcmp(s1.id, s2.id) < 0;
}
bool cmp_m(student s1, student s2)
{
	if (s1.score[2] != s2.score[2]) return s1.score[2] > s2.score[2];
	else return strcmp(s1.id, s2.id) < 0;
}
bool cmp_e(student s1, student s2)
{
	if (s1.score[3] != s2.score[3]) return s1.score[3] > s2.score[3];
	else return strcmp(s1.id, s2.id) < 0;
}
bool cmp_avg(student s1, student s2)
{
	if (s1.score[0] != s2.score[0]) return s1.score[0] > s2.score[0];
	else return strcmp(s1.id, s2.id) < 0;
}
void v_sort(student* s, bool (*cmp)(student, student), int n)
{
	sort(s, s + n, cmp);
}
void find_best(student* s) {//重点函数
	int min = 2020;
	for (int i = 0; i < 4; i++) {
		if (s->rank[i] < min) {
			min = s->rank[i];
			s->best_id = i;
		}
	}
	s->best = min;
}
int main()
{
	int N, M;
	scanf("%d%d", &N, &M);
	for (int i = 0; i < N; i++) {
		scanf("%s %d %d %d", s[i].id, &s[i].score[1], &s[i].score[2], &s[i].score[3]);
		s[i].score[0] = (int)((float)(s[i].score[1] + s[i].score[2] + s[i].score[3]) / 3 + 0.5);//四舍五入
	}
	v_sort(s, cmp_c, N);//对各学科排序,并得出各学科的排名
	s[0].rank[1] = 1;
	for (int i = 1; i < N; i++) {
		if (s[i].score[1] == s[i - 1].score[1])
			s[i].rank[1] = s[i - 1].rank[1];
		else s[i].rank[1] = i + 1;
	}
	v_sort(s, cmp_m, N);
	s[0].rank[2] = 1;
	for (int i = 1; i < N; i++) {
		if (s[i].score[2] == s[i - 1].score[2])
			s[i].rank[2] = s[i - 1].rank[2];
		else s[i].rank[2] = i + 1;
	}
	v_sort(s, cmp_e, N);
	s[0].rank[3] = 1;
	for (int i = 1; i < N; i++) {
		if (s[i].score[3] == s[i - 1].score[3])
			s[i].rank[3] = s[i - 1].rank[3];
		else s[i].rank[3] = i + 1;
	}
	v_sort(s, cmp_avg, N);
	s[0].rank[0] = 1;
	for (int i = 1; i < N; i++) {
		if (s[i].score[0] == s[i - 1].score[0])
			s[i].rank[0] = s[i - 1].rank[0];
		else s[i].rank[0] = i + 1;
	}
	//对于每个人,求得其最好排名和对应的科目ACME
	for (int i = 0; i < N; i++) {
		find_best(s + i);
	}
	for (int i = 0; i < M; i++) {//读入m个待查id
		scanf("%s", id[i]);
	}
	for (int i = 0; i < M; i++) {
		bool flag = false;
		for (int j = 0; j < N; j++) {
			if (strcmp(id[i], s[j].id) == 0) {
				flag = true;
				printf("%d %c\n", s[j].best, sub[s[j].best_id]);
			}
		}
		if (!flag) printf("N/A\n");
	}
	return 0;
}

标准答案:

//1012 The Best Rank (25分) https://pintia.cn/problem-sets/994805342720868352/problems/994805502658068480
#include <cstdio>
#include <algorithm>
int now;//全局变量,0-3对应四门课,可以省去4个不同的cmp函数
using namespace std;
struct student {
	int id;
	int score[4];
}s[2020];
int Rank[1000000][4] = { 0 };//rank[id][0]-[3]为4门课ACME对应的排名//C++有一个rank,为了不重名改为大写
char sub[5] = "ACME";
bool cmp(student s1, student s2)
{
	if (s1.score[now] != s2.score[now]) return s1.score[now] > s2.score[now];
	else
		return s1.id < s2.id;
}
int main()
{
	int N, M;
	scanf("%d%d", &N, &M);
	for (int i = 0; i < N; i++) {
		scanf("%d %d %d %d", &s[i].id, &s[i].score[1], &s[i].score[2], &s[i].score[3]);
		s[i].score[0] = (int)((float)(s[i].score[1]+ s[i].score[2]+ s[i].score[3]) / 3+0.5);//四舍五入
	}
	for (now = 0; now < 4; now++) {
		sort(s, s + N, cmp);
		Rank[s[0].id][now] = 1;
		for (int i = 1; i < N; i++) {
			if (s[i].score[now]==s[i-1].score[now]) {
				Rank[s[i].id][now] = Rank[s[i - 1].id][now];
			}
			else
			{
				Rank[s[i].id][now] = i + 1;
			}
		}
	}
	int query;
	while (M--)
	{
		scanf("%d", &query);
		int k = 0;
		if (Rank[query][0] == 0) printf("N/A\n");
		else
		{
			for (int i = 0; i < 4; i++) {
				if (Rank[query][i] < Rank[query][k])
					k = i;
			}
			printf("%d %c\n", Rank[query][k], sub[k]);
		}
	}
	return 0;
}

总结一下标准答案的可取之处:

1.id使用int而不是string

我看到题目a string of 6 digits想也没想就直接用字符数组存了。id设为int,配合上Rank数组(rank和c++本身的什么东西重名了)典型的用空间换时间,我需要遍历查找是否有这样的字符串,而数组可以随机访问,O1的复杂度,确实给力。

2.全局变量now

这个可真是厉害了,对比就可以发现,这个全局变量一下子就省去了四个不同的cmp函数和四次寻找排名,代码冗余度一下子减少好多,这也是标准答案的代码量只有我的一半的原因。其实当时我自己写着写着都怀疑人生了,而且最一开始我还不是用数组存rank的,到了要遍历寻找最小排名的时候才改过来的。

3.rank数组

这个二维数组结合了id和4门课的排名,把搜索id和寻找id对应最好排名结合起来,而且就用1个下标,直接输出最好排名和对应课程,都不需要存下来。除了妙我还能说什么呢?实在是妙啊,来!鼓掌!啪啪啪

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值