• PAT 甲级测试题目 -- 1012 The Best Rank


    题目链接

    题目描述

    输入小于等于 2000 的数据 N,M,分别表示 学生的总数 和 查询学生的数量
    输入 N 个学生的六位数 id 以及 C,M,E 三科成绩。输入 M 个查询学生的 id。
    要求输出:
    若被查询的 id 不存在,输出 N/A
    若被查询的 id 存在,输出 C,M,E,A(average 平均分) 四个成绩中排名最高的排名,以及对应的分数类型(C, M, E, A)。若有多余一个类型的分数相同,则按照 A > C > M > E 的优先序列输出 排名 和 分数类型

    分析

    由于各类成绩和学生 id 是对应关系,所以我想到使用 map<string, vector>类型存储录入的数据。
    由于要统计各类成绩排名,而且时间限制在 200ms,所以我想用空间换时间,定义了四个数组分别存储 C,M,E,A 四种类型的成绩。
    因为考虑到如果成绩相同,则排名相同,下一个排名为上一个的排名加上人数。例如对于 A 类型分数,100分 的有 2 人,99 分的有 1 人,则 100 分的两人排名均为 1,99 分的 1 人排名为 3。
    所以对于存储成绩的四个数组,先存储人数,然后根据人数更新排名。
    最后遍历的时候,对于每个学生的 vector,根据上述的四个数组确定最高的 排名 以及对应的 分数类型。
    最多共需要 32000 + 100 + 42000 = 14100 次循环。
    看了其他博主的解析,有用结构体实现的,不知道效率如何,我这边的代码跑了 16ms

    实现

    #include<iostream>
    #include<map>
    #include<vector>
    #include<string>
    #include<string.h>
    using namespace std;
    int main() {
    	// 存储学生总数 和 被检查的学生数量
    	int total_students, checked_students;
    
    	// 存储输入的学生信息,string 存储姓名,vector 存储成绩
    	map<string, vector<int>> students;
    
    	// 存储 C, M, E, A 四门科目成绩对应的人数,然后使用算法计算成绩对应的排名
    	int C[101], M[101], E[101], A[101];
    
    	// 初始化 C, M, E, A 四门科目成绩对应的人数为 0
    	memset(C, 0, sizeof(C));
    	memset(M, 0, sizeof(M));
    	memset(E, 0, sizeof(E));
    	memset(A, 0, sizeof(A));
    
    	// 存储存储学生总数 和 被检查的学生数量
    	cin >> total_students >> checked_students;
    
    	// 初始化学生信息
    	for (int i = 0; i < total_students; i++) {
    		// 记录学生的 id
    		string student_id; 
    
    		// 记录学生的成绩
    		int grade, average = 0; 
    		vector<int> grades;
    
    		// 输入学生 id
    		cin >> student_id;
    
    		// 输入学生成绩
    		for (int j = 0; j < 3; j++) {		
    			cin >> grade;
    			grades.push_back(grade);
    			average += grade;
    
    			// 记录三科成绩的人数
    			if (j == 0)
    				C[grade]++;			
    			if (j == 1)
    				M[grade]++;
    			if (j == 2)
    				E[grade]++;
    		}
    		// 记录平均成绩
    		A[average / 3]++;
    
    		// 插入平均成绩到最前面,方便按照题意中的优先级给出 rank
    		grades.insert(grades.begin(), average / 3);
    
    		// 插入学生信息
    		students.insert(pair<string, vector<int>>(student_id, grades));
    	}
    
    	// 根据录入的三科成绩人数计算排名
    	int rankC, rankM, rankE, rankA;
    	rankC = rankM = rankE = rankA = 1;
    
    	// 用于交换数据
    	int temp;
    	for (int i = 100; i >= 0; i--) {
    		// 更新 C 排名
    		temp = C[i];
    		if (temp != 0) {
    			C[i] = rankC;
    			rankC += temp;
    		}
    		
    		// 更新 M 排名
    		temp = M[i];
    		if (temp != 0) {
    			M[i] = rankM;
    			rankM += temp;
    		}
    
    		// 更新 E 排名
    		temp = E[i];
    		if (temp != 0) {
    			E[i] = rankE;
    			rankE += temp;
    		}
    
    		// 更新 A 排名
    		temp = A[i];
    		if (temp != 0) {
    			A[i] = rankA;
    			rankA += temp;
    		}
    	}
    
    	// 查找学生成绩
    	for (int i = 0; i < checked_students; i++) {
    		// 记录要查找的学生 id
    		string id;
    		cin >> id;		
    
    		// 如果找不到该学生
    		if (students.count(id) == 0) {
    			cout << "N/A";			
    		}
    
    		// 如果找到了
    		else {
    			// 定义 char 数组方便输出科目
    			char subject[4] = { 'A', 'C', 'M', 'E' };
    
    			// 定义 int 变量方便输出科目
    			int index, search_index = 0;
    
    			// 记录排名第一的科目以及科目的成绩,记录成绩方便从成绩表中查到排名
    			int topRank = 2001, rankGrade;
    
    			// 迭代器遍历 vector 容器,查询对应学生的每个科目的成绩
    			for (vector<int>::iterator iter = students[id].begin(); iter != students[id].end(); iter++) {
    				// 记录成绩
    				rankGrade = *iter;				
    
    				// 对每个科目进行查找
    				if (search_index == 0) {
    					if (topRank > A[rankGrade]) {
    						topRank = A[rankGrade];
    						index = 0;
    					}											
    				}					
    
    				if (search_index == 1) {
    					if (topRank > C[rankGrade]) {
    						topRank = C[rankGrade];
    						index = 1;
    					}
    				}
    
    				if (search_index == 2) {
    					if (topRank > M[rankGrade]) {
    						topRank = M[rankGrade];
    						index = 2;
    					}
    				}
    
    				if (search_index == 3) {
    					if (topRank > E[rankGrade]) {
    						topRank = E[rankGrade];
    						index = 3;
    					}
    				}
    
    				// 查找下一个科目
    				search_index++;
    			}
    
    			cout << topRank << " " << subject[index];			
    		}	
    		// 控制格式输出		
    		if (i != checked_students - 1)
    			cout << endl;
    	}
    	return 0;
    }
    

    希望能帮到大家!

  • 相关阅读:
    [转]Asp.net中基于Forms验证的角色验证授权
    [转]npm常用命令
    [转]utf8编码引起js输出中文乱码的解决办法
    LEFT JOIN 和 RIGHT JOIN 运算
    [转].NET 数字格式化:忽略末尾零
    [译]Pro ASP.NET MVC 3 Framework 3rd Edition 目录及说明
    微信授权登录
    百度快照更新慢怎么办
    linux爱好者必须掌握的命令,linux基础命令集合
    input输入框只能输入数字、字母相关组合(正则表达式)
  • 原文地址:https://www.cnblogs.com/Breathmint/p/10293400.html
Copyright © 2020-2023  润新知