PAT甲级真题1075 PAT 评测(可以锻炼程序能力)

PAT 的排名列表是根据状态列表产生的,状态列表中显示了所有提交记录的分数。

现在,请你为 PAT 生成排名列表。

输入格式
第一行包含三个整数 N,K,MN,K,M,分别表示总用户数量,题目数量,以及提交数量。

用户编号是从 0000100001 到 NN 的 55 位数字。

问题编号从 11 到 KK。

第二行包含 KK 个整数 p1,p2,…,pKp1,p2,…,pK,其中 pipi 表示第 ii 题的满分。

接下来 MM 行,每行包含一个提交信息,包括用户编号,题目编号,以及得分。

当提交无法正确编译时,得分显示 −1−1,否则是一个 [0,该题满分][0,该题满分] 范围内的整数。

注意,无法编译的情况虽然显示 −1−1,但得分上算作 00 分。

输出格式
以下列格式输出排名列表:

rank user_id total_score s[1] … s[K]
其中,rank 是根据 total_score 计算的,所以拥有相同 total_score 的用户的 rank 也相同。

s[i] 是第 ii 个问题获得的分数。

如果某个问题,用户从未提交过代码,则用 - 来表示这道题的分数。

如果某个问题,用户多次提交过代码,则取最高分为这道题的分数。

列表必须根据排名从前到后输出,对于排名相同的用户,根据满分题目的数量以降序对用户排序,如果仍有排名相同的情况,则按 ID 升序的顺序排序。

对于从未提交过任何代码,或者从未提交过任何编译通过的代码的用户,输出时不予考虑。

数据范围
1≤N≤1041≤N≤104,
1≤K≤51≤K≤5,
1≤M≤1051≤M≤105
每道题的满分为不超过 3030。

输入样例:
7 4 20
20 25 25 30
00002 2 12
00007 4 17
00005 1 19
00007 2 25
00005 1 20
00002 2 2
00005 1 15
00001 1 18
00004 3 25
00002 2 25
00005 3 22
00006 4 -1
00001 2 18
00002 1 20
00004 1 15
00002 4 18
00001 3 4
00001 4 2
00005 2 -1
00004 2 0
输出样例:
1 00002 63 20 25 - 18
2 00005 42 20 0 22 -
2 00007 42 - 25 - 17
2 00001 42 18 18 4 2
5 00004 40 15 0 25 -

#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <vector>

using namespace std;

const int K = 6;

int n, k, m;
int p_score[K];

struct Student
{
    string id;
    int grade[K];
    int total=0, cnt=0;

    Student(){}
    Student(string _id) : id(_id)
    {
        for (int i = 1; i <= k; i ++ ) grade[i] = -2;//-2是从来没有提交过或者没有通过编译
    }

    void calc()
    {
        for (int i = 1; i <= k; i ++ )
        {
            total += max(0, grade[i]);
            if (grade[i] == p_score[i]) cnt ++ ;
        }
    }

    bool has_submit()  //判断是否要输出
    {
        for (int i = 1; i <= k; i ++ )
            if (grade[i] >= 0)
                return true;
        return false;
    }

    bool operator< (const Student& t) const
    {
        if (total != t.total) return total > t.total;
        if (cnt != t.cnt) return cnt > t.cnt;
        return id < t.id;
    }
};

int main()
{
    unordered_map<string, Student> students; //一个编号对应一个学生

    scanf("%d%d%d", &n, &k, &m);
    for (int i = 1; i <= k; i ++ ) scanf("%d", &p_score[i]);

    while (m -- )
    {
        string u_id;
        char u_id_s[6];
        int p_id, grade;
        scanf("%s%d%d", u_id_s, &p_id, &grade);
        u_id = u_id_s;

        if (students.count(u_id) == 0) students[u_id] = Student(u_id);
        students[u_id].grade[p_id] = max(students[u_id].grade[p_id], grade);
    }

    vector<Student> res;
    unordered_map<string, Student>::iterator it;
    for (it=students.begin();it!=students.end();it++)
    {
        Student s = (*it).second;
        if (s.has_submit())
        {
            s.calc();
            res.push_back(s);
        }
    }

    sort(res.begin(), res.end());

    for (int i = 0, rank = 1; i < res.size(); i ++ )
    {
        if (i && res[i].total != res[i - 1].total) rank = i + 1;
        printf("%d %s %d", rank, res[i].id.c_str(), res[i].total);
        for (int j = 1; j <= k; j ++ )
            if (res[i].grade[j] == -2) printf(" -");
            else printf(" %d", max(0, res[i].grade[j]));
        puts("");
    }

    return 0;
}

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct node {
    int rank, id, total = 0;
    vector<int> score;
    int passnum = 0;
    bool isshown = false;
};
bool cmp1(node a, node b) {
    if(a.total != b.total)
        return a.total > b.total;
    else if(a.passnum != b.passnum)
        return a.passnum > b.passnum;
    else
        return a.id < b.id;
}
 
int main() {
    int n, k, m, id, num, score;
    scanf("%d %d %d", &n, &k, &m);
    vector<node> v(n + 1);
    for(int i = 1; i <= n; i++)
        v[i].score.resize(k + 1, -2);
    vector<int> full(k + 1);
    for(int i = 1; i <= k; i++)
        scanf("%d", &full[i]);
    for(int i = 0; i < m; i++) {
        scanf("%d %d %d", &id, &num, &score);
        v[id].id = id;
        v[id].score[num] = max(v[id].score[num], score);
        if(score != -1)
            v[id].isshown = true;
    }
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= k; j++) {
            if(v[i].score[j] != -1 && v[i].score[j] != -2)
                v[i].total += v[i].score[j];
            if(v[i].score[j] == full[j])
                v[i].passnum++;
        }
    }
    sort(v.begin() + 1, v.end(), cmp1);
    for(int i = 1; i <= n; i++) {
        v[i].rank = i;
        if(i != 1 && v[i].total == v[i - 1].total)
            v[i].rank = v[i - 1].rank;
    }
    for(int i = 1; i <= n; i++) {
        if(v[i].isshown == true) {
            printf("%d %05d %d", v[i].rank, v[i].id, v[i].total);
            for(int j = 1; j <= k; j++) {
                if(v[i].score[j]>=0)
                    printf(" %d", v[i].score[j]);
                else if(v[i].score[j] == -2)
                    printf(" -");
                else
                    printf(" 0");//没通过编译但是提交过
            }
            printf("\n");
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小王子y

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

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

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

打赏作者

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

抵扣说明:

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

余额充值