#P2723. 第2题-点名活动
          
                        
                                    
                      
        
              - 
          
          
                      1000ms
            
          
                      Tried: 31
            Accepted: 8
            Difficulty: 4
            
          
          
          
                       所属公司 : 
                              阿里
                                
            
                        
              时间 :2025年3月22日-阿里淘天(开发岗)
                              
                      
          
 
- 
                        算法标签>模拟          
 
第2题-点名活动
题解
题面描述
小兴的班上有n个人,他们总共要上m节课。每节课会进行一次点名,点名会随机选取ki个学生。如果这个学生没有到达,则会被记录一次“旷课”,每次“旷课”会导致该学生的平时分下降10点(下降到负数则视为0)。学生的最终成绩为平时成绩的40%加上期末考试成绩的60%。
思路
本题的核心任务是根据学生的到课情况、点名情况和期末成绩计算出每个学生的最终成绩。首先,初始化每个学生的平时分为100,并根据每节课的点名情况扣减未到课的学生平时分。然后,根据学生的期末成绩和调整后的平时成绩,按照给定的加权公式计算最终成绩。最后,将所有学生按最终成绩从高到低排序,若成绩相同则按学生编号升序输出。
- 
初始分数设置:
- 每个学生的初始平时分数是100,如果学生“旷课”了,平时分会下降10分,最小不低于0。
 - 学生的最终成绩是由平时成绩和期末成绩加权计算得到的,公式为: 最终成绩 = 平时成绩×0.4+期末成绩×0.6
 
 - 
数据处理:
- 每节课的到课情况可以通过两部分信息:学生到课情况和点名情况来更新学生的平时成绩。
 - 对于每节课,记录哪些学生旷课,减少他们的平时成绩,确保成绩不低于0。
 
 - 
排序:
- 计算完所有学生的最终成绩后,需要根据最终成绩进行排序,如果成绩相同,则根据编号升序排序。
 
 
C++
#include <iostream>
#include <vector>
#include <algorithm>
#include <iomanip>
using namespace std;
int main() {
    int n, m;
    cin >> n >> m;
    vector<int> final_exam(n);
    for (int i = 0; i < n; ++i) {
        cin >> final_exam[i];
    }
    vector<vector<int>> attendance(n, vector<int>(m));
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            cin >> attendance[i][j];
        }
    }
    vector<vector<int>> roll_call(m);
    for (int i = 0; i < m; ++i) {
        int k;
        cin >> k;
        roll_call[i].resize(k);
        for (int j = 0; j < k; ++j) {
            cin >> roll_call[i][j];
            roll_call[i][j]--; // 0-based index
        }
    }
    vector<double> regular_scores(n, 100.0);
    // 处理点名情况
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < roll_call[i].size(); ++j) {
            int student = roll_call[i][j];
            if (attendance[student][i] == 0) {
                // 学生旷课
                regular_scores[student] = max(regular_scores[student] - 10, 0.0);
            }
        }
    }
    // 计算最终成绩
    vector<pair<int, double>> final_scores(n);
    for (int i = 0; i < n; ++i) {
        double final_score = regular_scores[i] * 0.4 + final_exam[i] * 0.6;
        final_scores[i] = {i + 1, final_score}; // 存储学生编号与最终成绩
    }
    // 排序
    sort(final_scores.begin(), final_scores.end(), [](const pair<int, double>& a, const pair<int, double>& b) {
        if (a.second == b.second) return a.first < b.first;
        return a.second > b.second;
    });
    // 输出结果
    for (const auto& entry : final_scores) {
        cout << entry.first << " " << fixed << setprecision(2) << entry.second << endl;
    }
    return 0;
}
Python
def main():
    n, m = map(int, input().split())
    final_exam = list(map(int, input().split()))
    
    attendance = []
    for _ in range(n):
        attendance.append(list(map(int, input().split())))
    
    roll_call = []
    for _ in range(m):
        data = list(map(int, input().split()))
        k = data[0]
        roll_call.append(data[1:])
    
    regular_scores = [100.0] * n
    
    # 处理点名情况
    for i in range(m):
        for student in roll_call[i]:
            student -= 1  # 转为0-indexed
            if attendance[student][i] == 0:
                # 学生旷课
                regular_scores[student] = max(regular_scores[student] - 10, 0.0)
    
    final_scores = []
    for i in range(n):
        final_score = regular_scores[i] * 0.4 + final_exam[i] * 0.6
        final_scores.append((i + 1, final_score))  # 学生编号从1开始
    
    # 排序
    final_scores.sort(key=lambda x: (-x[1], x[0]))
    
    for student, score in final_scores:
        print(f"{student} {score:.2f}")
if __name__ == "__main__":
    main()
Java
import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(); // 学生数
        int m = sc.nextInt(); // 课程数
        int[] finalExam = new int[n];
        for (int i = 0; i < n; i++) {
            finalExam[i] = sc.nextInt();
        }
        int[][] attendance = new int[n][m];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                attendance[i][j] = sc.nextInt();
            }
        }
        List<List<Integer>> rollCall = new ArrayList<>();
        for (int i = 0; i < m; i++) {
            int k = sc.nextInt();
            List<Integer> rollList = new ArrayList<>();
            for (int j = 0; j < k; j++) {
                rollList.add(sc.nextInt() - 1); // 学生编号 0-based
            }
            rollCall.add(rollList);
        }
        double[] regularScores = new double[n];
        Arrays.fill(regularScores, 100.0); // 初始化所有学生的常规成绩为100
        // 处理点名情况
        for (int i = 0; i < m; i++) {
            for (int student : rollCall.get(i)) {
                if (attendance[student][i] == 0) {
                    // 学生旷课
                    regularScores[student] = Math.max(regularScores[student] - 10, 0.0);
                }
            }
        }
        // 计算最终成绩
        List<Student> finalScores = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            double finalScore = regularScores[i] * 0.4 + finalExam[i] * 0.6;
            finalScores.add(new Student(i + 1, finalScore)); // 存储学生编号与最终成绩
        }
        // 排序
        finalScores.sort((a, b) -> {
            if (Double.compare(a.score, b.score) == 0) {
                return Integer.compare(a.id, b.id);
            }
            return Double.compare(b.score, a.score);
        });
        // 输出结果
        for (Student student : finalScores) {
            System.out.printf("%d %.2f\n", student.id, student.score);
        }
        sc.close();
    }
    static class Student {
        int id;
        double score;
        Student(int id, double score) {
            this.id = id;
            this.score = score;
        }
    }
}
        题目内容
小兴的班上有n个人,他们总共要上m节课。每节课会有一次点名活动,第节课会随机选取ki个不同的学生进行点名,如果这个学生没有到达,则会被记录一次“旷课”。每个人起始的平时成绩为100,每次“旷课”会导致平时分下降10点(下降到负数则视为0)。
学生的最终成绩为平时成绩的40%加上期末考试成绩的60%。
现在小兴给你他们班上n个人每节课的上课情况以及期末考试成绩ai,请你按照最终成绩从大到小输出每个学生的编号以及他们的最终成绩(保留2位小数),如果最终成绩相同,则编号小的优先输出。
输入描述
第一行两个整数n,m(1≤n≤1000,1≤m≤100)
第二行n个整数a(0≤ai≤100)
接下来n行每行m个整数表示bi,j∈{0,1},如果bi,j=0则表示第j个人没有参加第1节课,否则这节课参加了。
接下来m行,第i行先输入一个整数ki(0≤ki≤n)代表第i节课点名的人数,随后在同一行输入ki个互不相同的整数,表示点到的学生编号。
输出描述
输出n行,按顺序输出每个人的编号、最终成绩(保留两位小数)。
样例1
输入
3 2
100 100 100
1 0
0 1
1 1
3 1 2 3
1 1
输出
3 100.00
1 96.00
2 96.00
说明
第一节课对所有人进行了点名,其中第二位同学没有到场,平时分变为90分。
第二节课对第一名学生进行了点名,没有到场,平时分变为90分。
最终三个人成绩分别为[96,96,100]。
样例2
输入
7 3
64 33 32 98 49 18 88
0 1 0
0 0 0
0 0 1
0 1 0
0 0 0
1 0 1
0 0 1
2 1 2
0 
2 1 2
输出
4 98.80
7 92.80
1 70.40
5 69.40
3 59.20
2 51.80
6 50.80