PAT A1075 PAT Judge (25 分) 排序

60 篇文章 0 订阅

       题目大意:给出N名考生的提交记录,总共有K道题,M条提交记录,要求按照总分降序、全对题目数量降序、考生id升序的方式进行排名,并输出每位考生每道题的得分。但是有一些额外要求:① 记录中得分如果是 -1,说明提交没有通过编译。② 没有任何题目通过编译的考生(也即没有得分大于-1的题目的考生),不输出。③ 输出的考生如果有题目得分是-1,应该输出0。④ 同一道题提交多次的,取最高分。⑤ 输出的考生如果有题目没有提交记录(即没有任何得分),应该输出 “-”。

      还是一贯的阅读理解题,由于题目的得分可以是-1及以上的值,每道题的初始成绩应当设置为-2。之后,输入的过程中,如果有得分大于-1的,说明该名考生需要输出。如果得分大于-1,判断是否需要更新该题得分,以及是否是满分。如果得分是-1,那么记录-1分。

但这样做有两个坑点(测试点4):

① 满分重复提交。所以对于该考生全对题目数量是否要+1需要先判断该题是否曾经得过满分了。

② 前面提交问题K有得分,但是之后又提交了一次-1分。所以对于分数是-1的情形,需要先判断该题是否曾经有得分,然后再决定是否要更新。

但是这两个坑点可以用一个很简单的方法一起避免,就是只有当输入的分数大于该题已经得到的分数时,才进入是否要更新分数的判断,否则直接忽略。如下:

    for (int i = 0; i < M; ++i)
    {
        int id, problem, score;
        scanf("%d%d%d", &id, &problem, &score);
        if(score > allUsers[id].score[problem])
        {
            if(score > -1)
            {
                allUsers[id].id = id;
                allUsers[id].hasSolution = true;
                allUsers[id].score[problem] = max(score, allUsers[id].score[problem]);
                if(score == fullScore[problem]) allUsers[id].perfectNum++;
            }
            else if(score == -1) allUsers[id].score[problem] = -1;
        }
    }

否则就要加两条判断:

    for (int i = 0; i < M; ++i)
    {
        int id, problem, score;
        scanf("%d%d%d", &id, &problem, &score);
        if(score > -1)
        {
            allUsers[id].id = id;
            allUsers[id].hasSolution = true;
            if(score == fullScore[problem] && allUsers[id].score[problem] < score) allUsers[id].perfectNum++;
            allUsers[id].score[problem] = max(score, allUsers[id].score[problem]);
        }
        else if(score == -1 && allUsers[id].score[problem] == -2) allUsers[id].score[problem] = -1;
    }

AC代码:

#include <vector>
#include <algorithm>
#include <cstdio>

using namespace std;

struct user
{
    int id;
    int score[6];
    int totalScore;
    int rank;
    int perfectNum;
    bool hasSolution;
    user():totalScore(0), perfectNum(0), hasSolution(false)
    {
        fill(score, score + 6, -2);
    }
    bool operator<(const user &other)
    {
        if(this->totalScore != other.totalScore) return this->totalScore > other.totalScore;
        else if(this->perfectNum != other.perfectNum) return this->perfectNum > other.perfectNum;
        else return this->id < other.id;
    }
}allUsers[10010];

int main()
{
    int N, K, M;
    scanf("%d%d%d", &N, &K, &M);
    vector<int> fullScore(K+1);
    for (int i = 1; i <= K; ++i)
        scanf("%d", &fullScore[i]);
    for (int i = 0; i < M; ++i)
    {
        int id, problem, score;
        scanf("%d%d%d", &id, &problem, &score);
        if(score > -1)
        {
            allUsers[id].id = id;
            allUsers[id].hasSolution = true;
            if(score == fullScore[problem] && allUsers[id].score[problem] < score) allUsers[id].perfectNum++;
            allUsers[id].score[problem] = max(score, allUsers[id].score[problem]);
        }
        else if(score == -1 && allUsers[id].score[problem] == -2) allUsers[id].score[problem] = -1;
    }
    vector<user> v;
    for (int i = 1; i <= N; ++i)
    {
        if(allUsers[i].hasSolution)
        {
            for (int j = 1; j <= K; ++j)
                allUsers[i].totalScore += max(0, allUsers[i].score[j]);
            v.push_back(allUsers[i]);
        }
    }
    sort(v.begin(), v.end());
    int rank = 1;
    v[0].rank = rank++;
    printf("%d %05d %d",v[0].rank, v[0].id, v[0].totalScore);
    for (int i = 1; i <= K; ++i)
    {
        if(v[0].score[i] > -2) printf(" %d", max(0, v[0].score[i]));
        else printf(" -");
        if(i == K) printf("\n");
    }
    for (int i = 1; i < v.size(); ++i)
    {
        if(v[i].totalScore == v[i-1].totalScore) v[i].rank = v[i-1].rank;
        else v[i].rank = rank;
        rank++;
        printf("%d %05d %d",v[i].rank, v[i].id, v[i].totalScore);
        for (int j = 1; j <= K; ++j)
        {
            if(v[i].score[j] > -2) printf(" %d", max(0, v[i].score[j]));
            else printf(" -");
            if(j == K) printf("\n");
        }
    }
    return 0;
}


优化一点的代码,遍历次数多了点,但是思路很自然:先读入所有数据,每次更新分数为已读入的最大值,并确定哪些人可以被输出(至少有一个分数大于-1)。之后,对于这些可以被输出的人,再统计他们的总分以及满分个数。最后排名。

#include <bits/stdc++.h>

using namespace std;

const int MAXN = 10010;

struct user
{
    int id;
    vector<int> score;
    int totalScore;
    int perfectCnt;
    int rank;
    bool printOut;
    user():totalScore(0), perfectCnt(0), printOut(false){};
    bool operator <(const user& other)
    {
        if(this->totalScore != other.totalScore) return this->totalScore > other.totalScore;
        else if(this->perfectCnt != other.perfectCnt) return this->perfectCnt > other.perfectCnt;
        else return this->id < other.id;
    }
}allUsers[MAXN];

int main()
{
    int N, K, M;
    scanf("%d%d%d", &N, &K, &M);
    vector<int> fullScore(K+1, 0);
    for (int i = 1; i <= K; ++i)
    {
        scanf("%d", &fullScore[i]);
    }
    for (int i = 1; i <= N; ++i)
    {
        allUsers[i].score = vector<int>(K+1, -2);
    }
    for (int i = 0; i < M; ++i)
    {
        int id, problem, score;
        scanf("%d%d%d", &id, &problem, &score);
        allUsers[id].id = id;
        allUsers[id].score[problem] = max(allUsers[id].score[problem], score);
        if(score > -1) allUsers[id].printOut = true;
    }
    vector<user> rankList;
    for (int i = 1; i <= N; ++i)
    {
        if(allUsers[i].printOut)
        {
            for (int j = 1; j <= K; ++j)
            {
                allUsers[i].totalScore += max(0,allUsers[i].score[j]);
                allUsers[i].perfectCnt += allUsers[i].score[j] == fullScore[j] ? 1 : 0;
            }
            rankList.push_back(allUsers[i]);
        }
    }
    sort(rankList.begin(), rankList.end());
    int rank = 1;
    rankList[0].rank = rank++;
    for (int i = 1; i < rankList.size(); ++i)
    {
        if(rankList[i].totalScore == rankList[i-1].totalScore) rankList[i].rank = rankList[i-1].rank;
        else rankList[i].rank = rank;
        rank++;
    }
    for (int i = 0; i < rankList.size(); ++i)
    {
        printf("%d %05d %d", rankList[i].rank, rankList[i].id, rankList[i].totalScore);
        for (int j = 1; j <= K; ++j)
        {
            if(rankList[i].score[j] > -2) printf(" %d", max(0, rankList[i].score[j]));
            else printf(" -");
        }
        printf("\n");
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值