2019河北省大学生程序设计竞赛(重现赛)D.榜单(榜单模拟)

题目链接:https://ac.nowcoder.com/acm/contest/903/D

解题心得:

  • 上次我们学院院赛我队友就出了个和这个几乎一毛一样的题去恶心参赛人员,结果这次居然遇到和我队友想法一样的出题人了。
  • 其实很简答就是模拟榜单嘛,写的时候把代码写规范一点,脑子不要发昏认认真真写就行了。写完一发AC。


#include <bits/stdc++.h>

using namespace std;
map <string, int> map_name;
int id, max_name_len, n;//记录有多少个人进行了有效提交,有效队伍名字最长的长度,题目数量

struct Person {//把每个队伍单独抽象出来
    int penalty, solved;//记录罚时次数,解决了多少个题
    string name;//记录名字
    bool if_pass[50];//记录每个题是否通过了
    int each_penelty[50];//每个题被罚时次数

    bool operator < (const Person& y) const {//排名
        Person x = *this;
        if(x.solved != y.solved)
            return x.solved > y.solved;
        else// if(x.penalty != y.penalty)
            return x.penalty < y.penalty;
    }
}p[5010];

bool cmp(Person x, Person y) {
    if(x.solved != y.solved)
        return x.solved > y.solved;
    else if(x.penalty != y.penalty)
        return x.penalty < y.penalty;
    // if(x.name != y.name)
    return x.name < y.name;
}

void checke_sigal(char s[]) {//对每一条记录进行处理
    int h, m;
    sscanf(s, "%d:%d", &h, &m);
    m = h*60 + m;//提交时间

    int w = int(s[6] - 'A');
    int result = -1, Next_pos = -1;//记录结果结果编号和题目中给出的对应,下一个需要寻找的信息在字符串中的位置
    if(s[8] == 'A') {
        result = 1;
        Next_pos = 8 + strlen("Accepted ");
    } else if(s[8] == 'W') {
        result = 2;
        Next_pos = 8 + strlen("Wrong Answer ");
    } else if(s[8] == 'T') {
        result = 3;
        Next_pos = 8 + strlen("Time Limit Exceeded ");
    } else if(s[8] == 'C') {//CE看作无效提交,直接不处理,首先排除掉
        return ;
    } else if(s[8] == 'M') {
        result = 5;
        Next_pos = 8 + strlen("Memory Limit Exceeded ");
    } else if(s[8] == 'O') {
        result = 6;
        Next_pos = 8 + strlen("Output Limit Exceeded ");
    } else if(s[8] == 'R') {
        result = 7;
        Next_pos = 8 + strlen("Runtime Error ");
    } else if(s[8] == 'P') {
        result = 8;
        Next_pos = 8 + strlen("Presentation Error ");
    }

    string name = s+Next_pos;//记录队伍名字
    if(map_name.count(name) == 0) {
        map_name[name] = ++id;
    }

    int which = map_name[name];
    p[which].name = name;
    max_name_len = max(max_name_len, int(name.length()));
    if(p[which].if_pass[w]) return ;

    if(result == 1) {//AC了
        p[which].if_pass[w] = true;
        p[which].penalty += p[which].each_penelty[w]*20 + m;
        p[which].solved ++;
    } else {//除了AC都罚时
        p[which].each_penelty[w]++;
    }
}

void Print(string ss, int cnt) {
    cout<<ss;
    for(int i=0;i<cnt;i++) {
        printf(" ");
    }
}

void Print() {//按照格式打印就行了
    string ss;
    Print(ss="Rank", 2);
    Print(ss="Who", max_name_len-3+2);
    Print(ss="Solved", 2);
    Print(ss="Penalty", 0);
    for(int i=0;i<n;i++) {
        printf("    %c", 'A' + i);
    }
    printf("\n");
    int rank;
    for(int i=1;i<=id;i++) {
        rank = lower_bound(p+1, p+1+id, p[i]) - p;//排名直接lower_bound找就行了
        printf("%4d  ", rank);
        Print("", max_name_len-p[i].name.length());
        printf("%s  ",p[i].name.c_str());
        printf("%6d  ",p[i].solved);
        printf("%7d", p[i].penalty);
        for(int j=0;j<n;j++) {
            if(!p[i].if_pass[j]) {
                if(p[i].each_penelty[j] == 0)
                    printf("     ");
                else
                    printf("   -%d", p[i].each_penelty[j]);
            } else {
                if(p[i].each_penelty[j] == 0) {
                    printf("    +");
                } else {
                    printf("   +%d", p[i].each_penelty[j]);
                }
            }
        }
        printf("\n");
    }
}

int main() {
//    freopen("in", "r", stdin);
//    freopen("out", "w", stdout);
    scanf("%d", &n);
    getchar();
    char record[2100];
    while(fgets(record, 2100, stdin)) {
        int len=strlen(record);
        record[len-1] = 0;
        if(record[0] == 'G') break;
        checke_sigal(record);
    }

    sort(p+1, p+1+id, cmp);

    Print();
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值