OJ评分,爆零(×)大力出奇迹(√)。c++

实验使用的实时评测系统,具有及时获得成绩排名的特点,那它的功能是怎么实现的呢?

我们千辛万苦怼完了不忍直视的程序并提交以后,评测系统要么返回AC,要么是返回各种其他的错误,不论是怎样的错法,它总会给你记上一笔,表明你曾经在这儿被坑过,而当你历经千辛终将它AC之后,它便会和你算笔总账,表明这题共错误提交了几次。

在岁月的长河中,你通过的题数虽然越来越多,但通过每题时你所共花去的时间(从最开始算起,直至通过题目时的这段时间)都会被记录下来,作为你曾经奋斗的痕迹。特别的,对于你通过的题目,你曾经的关于这题的每次错误提交都会被算上一定的单位时间罚时,这样一来,你在做出的题数上,可能领先别人很多,但是在做出同样题数的人中,你可能会因为罚时过高而处于排名上的劣势。

例如某次考试一共八道题(A,B,C,D,E,F,G,H),每个人做的题都在对应的题号下有个数量标记,负数表示该学生在该题上有过的错误提交次数但到现在还没有AC,正数表示AC所耗的时间,如果正数a跟上了一对括号,里面有个正数b,则表示该学生AC了这道题,耗去了时间a,同时曾经错误提交了b次。例子可见下方的样例输入与输出部分.

输入数据包含多行,第一行是共有的题数n(1≤n≤12)以及单位罚时m(10≤m≤20),之后的每行数据描述一个学生的信息,首先是学生的用户名(不多于10个字符的字串)其次是所有n道题的得分现状,其描述采用问题描述中的数量标记的格式,见样例输入。

根据这些学生的得分现状,输出一个实时排名。实时排名显然先按AC题数的多少排,多的在前,再按时间分的多少排,少的在前,如果凑巧前两者都相等,则按名字的字典序排,小的在前。每个学生占一行,输出名字(10个字符宽),做出的题数(2个字符宽,右对齐)和时间分(4个字符宽,右对齐)。名字、题数和时间分相互之间有一个空格。数据保证可按要求的输出格式进行输出。

sample input:
输入表格

sample output:

TT 5 348
yjq 4 342
GuGuDong 3 197
hrz 3 256
Zjm 2 316
OMRailgun 0 0

思路:
1.由于实时排名是先按AC题数的多少排,多的在前;再按时间分的多少排,少的在前;最后按名字的字典序排,小的在前。所以很明显是一个基数排序的题。
2.那么根据比较的条件,首先需要定义结构体来存储每一个学生的姓名、AC题数和分数。然后写一个cmp函数用来完成两个学生之间的基数排序,注意学生名字的字典序我们可以使用string头文件中带的用于比较字符串的strcmp函数。返回字典序排序小的在前。
3.由于可能包含多组数据,所以使用(scanf("%s",stu[temp].name)!=EOF)来判断结束,这里需要注意一件事就是在本机上通过键盘输入的方式进行程序运行的时候,程序识别不到文件尾EOF。所以想要输入结束符的话,unix系统按ctrl+d键,windows中按ctrl+z键,标准输入输出将会识别一个eof.
4.在计算AC题数和罚时的时候注意处理字符串时若发现输入的有负号或者是0,则说明这道题没有过,不计算AC和罚时;若发现有括号存在(只需要扫描是否存在左括号)则左括号内的值就是做错的次数。由于最终的时间分是*所有做过的题的时间+错误次数×m(单位罚时)*所以我们可以利用字符扫描进行计算
5.对于输出,printf默认的输出是左对齐的;如果在%和d中加上负号和位数:printf("%-10d\n",a);说明输出数字的宽度是十,如果位数小于10则直接拿空格补全,如果超过10则打印所有数字(下面用宽度5做测试)
在这里插入图片描述
在%和d中间加上数字就会右对齐,不足补上空格,超过不截断。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;

int n,m;

struct person
{
	char name[20];
	int count;
	int score;
}stu[10000];

bool cmp(person x,person y)
{
    if(x.count!=y.count)
    return x.count>y.count;
    else if(x.score!=y.score)
    return x.score<y.score;
    else
    return strcmp(x.name,y.name)<0;
}
int main()
{
    cin>>n>>m;//题数+单位阀时 
    int temp=0;
    char ch[10];
    while(scanf("%s",stu[temp].name)!=EOF)
    {
        stu[temp].count=0;
		stu[temp].score=0;
        for(int i=0;i<n;i++)
        {
            scanf("%s",ch);
            if(ch[0]=='-')
                continue;
            if(strcmp(ch,"0")==0)
                continue;
            stu[temp].count++;//非以上情况加分 
            int tmp=0;
            int j=0; 
            for(j=0;j<strlen(ch);j++)
            {
                if(ch[j]=='(') break;
                tmp=tmp*10+ch[j]-'0';
            }
            stu[temp].score+=tmp;
            tmp=0;
           if(j<strlen(ch))
            {
               for(int k=j+1;k<strlen(ch)-1;k++)
               {
                    tmp=tmp*10+ch[k]-'0';
                }
            }
            stu[temp].score+=tmp*m;
        }
        temp++;
    }
    sort(stu,stu+temp,cmp);                                                                                                             
	for(int i=0;i<temp;i++)
	{                   
	printf("%-10s %2d %4d\n",stu[i].name,stu[i].count,stu[i].score);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值