当前位置:首页 > GESP > 2024年GESP五级成绩排序算法解析:洛谷B3968代码实现与优化思路

2024年GESP五级成绩排序算法解析:洛谷B3968代码实现与优化思路

3个月前 (07-18)

2024年GESP五级成绩排序算法解析:洛谷B3968代码实现与优化思路 GESP五级 成绩排序 洛谷题解 GESP题解 双指针 C++ 第1张

一、题目解读

题目要求对n名学生的语文、数学、英语成绩进行排序,并输出按原始输入顺序的排名。排序规则需依次比较总分、语数总分、语数最高分,若完全相同时保持原始顺序。需处理并列排名,确保相同成绩的学生获得同一名次。

二、解题思路

1. 设计Student结构体存储学生信息(ID、各科成绩、总分、语数相关分数、排名),避免数据分散。

2. 自定义compare函数实现多维比较:总分>语数总分>语数最高分,利用短路逻辑提升效率。

3. 通过排序与遍历处理并列排名:对副本排序后,找到连续相同成绩的区间,分配相同排名。

4. 利用映射将排序后的排名还原至原始输入顺序,确保输出正确。

三、解题步骤

1. 数据输入与预处理:循环读取n名学生成绩,计算总分、语数总分及最高分,并记录ID。

2. 排序副本生成:复制学生数据至sorted数组,使用自定义compare函数排序,避免破坏原始顺序。

3. 并列排名计算:遍历sorted,通过双指针找到成绩相同区间,为区间内学生统一分配排名。

4. 排名映射与输出:创建original_order_rank数组,根据ID映射排名,按原始顺序输出。

四、代码与注释

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

// 学生结构体,存储原始数据和计算后的各种分数
struct Student {
    int id;         // 原始输入顺序
    int chinese;    // 语文成绩
    int math;       // 数学成绩
    int english;    // 英语成绩
    int total;      // 三科总分
    int cm_sum;     // 语文+数学总分
    int cm_max;     // 语文和数学中的最高分
    int rank;       // 最终排名
};

// 自定义比较函数,用于排序
bool compare(const Student &a, const Student &b) {
    if (a.total!= b.total) return a.total > b.total; // 优先比较总分
    if (a.cm_sum!= b.cm_sum) return a.cm_sum > b.cm_sum; // 次比较语数总分
    if (a.cm_max!= b.cm_max) return a.cm_max > b.cm_max; // 再比较语数最高分
    return false; // 完全相等时保持原顺序
}

int main() {
    int n;
    cin >> n;
    
    vector<Student> students(n);
    
    // 读取输入数据并计算各种分数
    for (int i = 0; i < n; ++i) {
        cin >> students[i].chinese >> students[i].math >> students[i].english;
        students[i].id = i;
        students[i].total = students[i].chinese + students[i].math + students[i].english;
        students[i].cm_sum = students[i].chinese + students[i].math;
        students[i].cm_max = max(students[i].chinese, students[i].math);
    }
    
    // 复制一份用于排序
    vector<Student> sorted = students;
    sort(sorted.begin(), sorted.end(), compare);
    
    // 计算排名,处理并列情况
    for (int i = 0; i < n; ) {
        int j = i;
        // 找到所有与当前学生成绩相同的连续学生
        while (j < n &&!compare(sorted[i], sorted[j]) &&!compare(sorted[j], sorted[i])) {
            ++j;
        }
        // 为这些学生设置相同的排名
        for (int k = i; k < j; ++k) {
            sorted[k].rank = i + 1;
        }
        i = j;
    }
    
    // 将排名信息映射回原始顺序
    vector<int> original_order_rank(n);
    for (int i = 0; i < n; ++i) {
        original_order_rank[sorted[i].id] = sorted[i].rank;
    }
    
    // 按原始输入顺序输出排名
    for (int i = 0; i < n; ++i) {
        cout << original_order_rank[i] << endl;
    }
}

注:代码中通过sort函数与自定义比较函数实现多维排序,利用双指针处理并列排名,通过映射还原原始顺序,确保逻辑清晰且高效。

五、总结

本解法核心在于结构体的合理设计与多维排序规则的实现,通过副本排序+映射技巧避免数据混乱。处理并列排名时,利用短路逻辑优化比较效率,双指针遍历减少冗余计算。代码简洁且符合竞赛要求,为同类排序问题提供了可复用的模板。需注意:排序函数需严格遵循题目规则顺序,并列处理需确保区间完整性。


原创内容 转载请注明出处

分享给朋友:

相关文章

力扣119题:从O(n²)到O(2n):杨辉三角高效空间优化

力扣119题:从O(n²)到O(2n):杨辉三角高效空间优化

题目重解:给定一个非负索引 rowIndex,返回杨辉三角的第 rowIndex 行。不同于生成整个杨辉三角,这道题要求我们只返回特定行,且空间复杂度应尽可能优化。例如输入3,需要返回[1,3,3,1...

IOI 1994 洛谷1216:如何用动态规划高效解决数字三角形问题?附完整代码解析

IOI 1994 洛谷1216:如何用动态规划高效解决数字三角形问题?附完整代码解析

题目重解给定一个由数字组成的三角形结构,从顶部出发,每次可以移动到下方相邻的数字,最终到达底部。我们的目标是找到一条路径,使得路径上经过的数字总和最大。这个问题在实际中有许多应用场景,如最优路径规划、...

2024 GESP五级「奇妙数字」深度解析:高效解题代码与数学逻辑揭秘(洛谷B4070)

2024 GESP五级「奇妙数字」深度解析:高效解题代码与数学逻辑揭秘(洛谷B4070)

一、题目解读2024年GESP(青少年编程能力等级测试)五级题目「奇妙数字」(对应洛谷平台题目B4070),要求选手根据特定规则计算输入数字的“奇妙值”。题目核心在于挖掘数字的数学特性,结合质因数分解...

牛客14496题解:括号最大深度问题(栈思想与代码优化)

牛客14496题解:括号最大深度问题(栈思想与代码优化)

一、题目解读牛客14496题要求计算给定括号字符串中的最大深度。例如,对于字符串 "(()())",最大深度为2。题目考察对括号嵌套结构的理解,以及如何通过编程找到最深嵌套层次。二...

力扣3112题解法:带时间限制的最短路径问题解析(C++代码)

力扣3112题解法:带时间限制的最短路径问题解析(C++代码)

一、题目解读力扣3112题要求解决带时间限制的最短路径问题:给定一个有向图,节点具有消失时间,需计算从起点到各节点的最短路径,且路径总时间不能超过节点的消失时间。题目难点在于需在传统最短路径算法(如D...

【洛谷1184题解析】用C++高效解决地点匹配问题(附代码与解题思路)

【洛谷1184题解析】用C++高效解决地点匹配问题(附代码与解题思路)

一、题目解读洛谷1184题要求处理一组地点列表与行程记录,统计其中匹配的天数。题目难点在于高效处理带有空格的字符串输入,以及快速判断每日行程是否在高手可去地点集合中。需要兼顾输入格式解析与算法效率。二...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。