1085 PAT单位排行 (25 分)

1085 PAT单位排行 (25 分)

题意描述:

每次 PAT 考试结束后,考试中心都会发布一个考生单位排行榜。本题就请你实现这个功能。

输入格式:
输入第一行给出一个正整数 N(≤10^​5​​ ),即考生人数。随后 N 行,每行按下列格式给出一个考生的信息:

准考证号 得分 学校

其中准考证号是由 6 个字符组成的字符串,其首字母表示考试的级别:B代表乙级,A代表甲级,T代表顶级;得分是 [0, 100] 区间内的整数;学校是由不超过 6 个英文字母组成的单位码(大小写无关)。注意:题目保证每个考生的准考证号是不同的。

输出格式:
首先在一行中输出单位个数。随后按以下格式非降序输出单位的排行榜:

排名 学校 加权总分 考生人数

其中排名是该单位的排名(从 1 开始);学校是全部按小写字母输出的单位码;加权总分定义为乙级总分/1.5 + 甲级总分 + 顶级总分*1.5的整数部分;考生人数是该属于单位的考生的总人数。

学校首先按加权总分排行。如有并列,则应对应相同的排名,并按考生人数升序输出。如果仍然并列,则按单位码的字典序输出。

输入样例:

10
A57908 85 Au
B57908 54 LanX
A37487 60 au
T28374 67 CMU
T32486 24 hypu
A66734 92 cmu
B76378 71 AU
A47780 45 lanx
A72809 100 pku
A03274 45 hypu

输出样例:

5
1 cmu 192 2
1 au 192 3
3 pku 100 1
4 hypu 81 2
4 lanx 81 2

解题思路:
Alice: 题目倒是讲的挺明白的,就是输入有10000个,估计用Python写又要超时,有得凉凉了。┐(・o・)┌
Bob: 对啊,用C++ 的话,还得处理怎么从校名这个字符串映射到 成绩和 学生总数这个问题。也不知道 C++ 有没有字典啊,还是对C++ 模板库不哦,用C++处理字符串我也不熟。
Alice: 那你快学呀,这样吧,你先用Python 写,如果实在过不去,我去看看别人用C++ 怎么写的。ヾ(◍°∇°◍)ノ゙
Bob: ∠(°ゝ°) 【(╯▽╰) 】


代码:

  • Bob’s Python 在这里插入图片描述 Version ?
from functools import cmp_to_key


def main():
    N = int(input())
    # 接收输入的正整数 N
    global data
    data = {}
    for x in range(N):
        # 依次接收N个考生的 数据
        ID, score, school = (z for z in input().split())
        # 元组拆包
        school = school.lower()
        data.setdefault(school, [0, 0])
        # number of stu, total score

        if ID[0] == 'B':
            data[school][1] += float(score) / 1.5
        elif ID[0] == 'A':
            data[school][1] += float(score)
        else:
            data[school][1] += float(score) * 1.5
        # 将这位考生的分数 做变化后 加到对应的学校那儿

        data[school][0] += 1
        # 对应的学校那儿的考生人数加一

    for school in data:
        data[school][1] = int(data[school][1])
        # 排序之前,根据题意只保留 该学校成绩的整数部分

    answer = sorted(data, key=cmp_to_key(compare), reverse=True)
    # 根据题意排序
    pre_rank = rank = 1
    # pre_rank 是排好序的列表中前一项的排名
    # rank 是当前项的排名
    print(len(answer))
    # 输出学校总数
    school = answer[0]
    print("{} {} {} {}".format(rank, school,
                               data[school][1], data[school][0]))
    # 输出排名第一的学校的信息
    for index in range(1, len(answer)):
        if data[answer[index]][1] == data[answer[index - 1]][1]:
            rank = pre_rank
            # 总分与前一任学校相等
        else:
            pre_rank = rank = index + 1
            # 否则得到一个新的排名
        school = answer[index]
        print("{} {} {} {}".format(rank, school,
                                   data[school][1], data[school][0]))


def compare(a, b):
    # a, b 都是 data 的 key, 且 a 在前 b在后。返回负数时交换data[a], data[b]
    if data[a][1] != data[b][1]:
        # 总分不等
        return data[a][1] - data[b][1]
    else:
        # 总分相等,学校人数不等
        if data[a][0] != data[b][0]:
            return data[b][0] - data[a][0]
        else:
            # 总分相等,学校人数也相等
            if a > b:
                # 校名a 的字典序 大于 校名b的字典序
                return -1
            else:
                return 1


if __name__ == '__main__':
    main()


  • Alice’s Bravo C++ Version:
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
using namespace std;

// 定义一个结构体,用来存储最后要输出的信息
struct node{
	string school;
	int score;
	int cnt;
};
 
// c++ sort函数cmp参数要写成  返回值是bool类型的函数   
// 返回False 时交换元素的位置 
bool compare(node a, node b){
	if (a.score != b.score){
		return a.score > b.score;
		// 按成绩降序 
	}else if (a.cnt != b.cnt){
		return a.cnt < b.cnt;
		// 按学校人数升序 
	}else{
		return a.school < b.school;
		// 按校名字典序 升序 
	}
}

int main(){
	int N;
	int score;
	string ID, school;
	scanf("%d", &N);
	// 接收输入的正整数 N 
	map<string, int> cnt;
	map<string, double> scores;
	// c++ 中的map 类似有 Python 中的字典,不同的是,仅仅能建立两种数据类型之间的映射。 
	//(as far as I know) 
	for(int i=0; i<N; ++i){
		cin >> ID;
		scanf("%d", &score);
		cin >> school; 
		// 输入某人的ID, 成绩, 校名 
		for(int j=0; j<school.length(); ++j){
			school[j] = tolower(school[j]);
		}
		//把校名转换成小写 
		
		if(ID[0] == 'B'){
			scores[school] += double(score) / 1.5; 
		}else if(ID[0] == 'T'){
			scores[school] += double(score) * 1.5;
		}else{
			scores[school] += double(score);
		}
		// 把该生的成绩加到对应的学校那儿去 
		cnt[school] += 1;
		// 对应的学校那儿的学生人数也加一 
	}
	/* two methods to Traversing the map
	map <string, double>::iterator iter;
	iter = scores.begin();
	while (iter != scores.end()){
		cout << iter->first << " " << iter->second << endl;
		iter ++;
	}
	
	for(map<string, int>::iterator iter = cnt.begin(); iter != cnt.end(); iter++){
		cout << iter->first << " " << iter->second << endl;
	}
	*/
	vector<node> score_and_cnt;
	// 由于最终一共有多少学校是未知的,我们使用vector(动态数组)来存储  
	for(map<string, int>::iterator iter = cnt.begin(); iter != cnt.end(); iter++){
		node temp = {iter->first, int(scores[iter->first]), iter->second};
		score_and_cnt.push_back(temp);
	}
	// 将某个学校的 校名,成绩,人数,依次取出组成一条node类型的数据 ,存入score_and_cnt中 
	sort(score_and_cnt.begin(), score_and_cnt.end(), compare);
	// 按题意对 score_and_cnt 排序 
	// one method to Traversing the vector 
	int pre_score = -1, rank = 0;
	cout << score_and_cnt.size() << endl;
	// 输出学校总数 
	for(int i=0; i<score_and_cnt.size(); ++i){
		if(score_and_cnt[i].score != pre_score){
			// 当前学校分数与前一个学校的总分不等,则排名更新
			rank = i + 1;
			pre_score = score_and_cnt[i].score;
		}
		// 否则,排名,前一名的总分都不变 
		cout << rank << " " << score_and_cnt[i].school << " " 
		<< score_and_cnt[i].score << " " << score_and_cnt[i].cnt << endl;
		// 输出排名,校名,分数,人数 
	}
	
	
	
	
	
	return 0;
} 

易错点:

  • Python 容易超时,毕竟10000条数据,还要排序。咱也不知道还能不能再优化一下,还能不能再快一点。(¦3」∠)__(¦3」∠)
  • 保留总分的整数部分需要先求出总分之后再保留整数部分,不能先保留了整数部分再求出来的总分。

总结:

  • Bob’s Python 在这里插入图片描述 Version ?
    python
  • Alice’s Bravo C++ Version:
    c++ version

### 关于PAT单位排行C语言测试点2的解析 #### 输入规格说明 对于每个测试案例,在一行中给出总考生数量。随后按照指定格式打印最终排名列表[^3]。 #### 准考证号结构析 准考证号由6个字符构成,首位字母指示考试等级:`B`表示乙级,`A`表示甲级,而`T`则对应顶级。每位考生的成绩位于区间\[0, 100\]之间,并且学校通过最多含6个小写字母(忽略大小写差异)来编码识别[^4]。 #### 数据处理逻辑实现 为了完成这一任务,可以采用如下方法: - **读取输入数据**:接收并解析来自标准输入的数据流; - **构建字典存储成绩表**:创建一个字典用于保存各学校的累计数以及参与人数; - **遍历所有记录更新统计信息**:逐条处理每一条参赛者的信息,依据所属学校累积相应值; - **计算平均与排序**:基于上述统计数据计算各个机构的加权评,并据此排列名次; - **输出结果**:依照规定模板展示最终排行榜单。 以下是Python代码片段演示如何执行这些操作: ```python from collections import defaultdict def process_input(): n = int(input()) schools = defaultdict(lambda : {'total_score': 0, 'count': 0}) for _ in range(n): id_, score_str, school_code = input().split() score = int(score_str) # Update statistics for this school schools[school_code.lower()]['total_score'] += score schools[school_code.lower()]['count'] += 1 return dict(schools) def calculate_weighted_scores(school_data): weighted_scores = [] for code, stats in school_data.items(): avg_score = round(stats['total_score']/stats['count']) entry = { 'code': code, 'avg_score': avg_score, 'num_students': stats['count'] } weighted_scores.append(entry) return sorted(weighted_scores, key=lambda x:(-x['avg_score'], x['code'])) if __name__ == "__main__": data = process_input() results = calculate_weighted_scores(data) print(len(results)) for res in results: print(f"{res['code']} {res['num_students']} {res['avg_score']}") ``` 该程序首先收集所有的输入数据并将它们类整理到不同学校下,接着计算出每个学校的平均得及其参加的学生数目,最后按要求输出排序后的表格。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花花生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值