week2-B 成绩排名

题目描述

程序设计思维作业和实验使用的实时评测系统,具有及时获得成绩排名的特点,那它的功能是怎么实现的呢?

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

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

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

Input

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

Output

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

Sample Input

在这里插入图片描述

Sample Output

在这里插入图片描述

思路分析:

本题的思路很明确,创建结构体Student存放学生姓名、AC数和字典序,通过输入的数据计算每个人的AC题数和罚时,利用sort函数进行排序(自定义排序函数cmp(),按AC数降序,罚时、名字的字典序升序)。

关于输入:每题的结果中包含括号,定义字符数组result接受输入的每题结果,当result[0]==’0’/’-’时该题没通过不用做处理,在for循环中判断result[i]是否为左括号,左括号前为该题用时,左括号后为该题错误次数(这里也可以利用sscanf,用占位符,按格式读入)。同时对于字符变量只需要减‘0’就可以得到对应数值。

关于输出:默认是左对齐,可以通过cout<<std::left/right调整为左、右对齐。setw(n)来控制输出长度。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <iomanip>
#include <cstdio>
using namespace std;
const int MAXN = 10000;
struct Student
{
 char name[10];
 int AC;
 int penalty;
};

bool cmp(Student a,Student b)
{//第一关键词降序,第二、第三关键词升序 
 if(a.AC!=b.AC)
  return a.AC>b.AC;
 else if(a.penalty!=b.penalty)
  return a.penalty<b.penalty;
 else 
     return strcmp(a.name,b.name)<0;
}

int main()
{
 Student s[MAXN];
 int n,m;
 cin>>n>>m;
 char result[10];
 char Name[10];
 int i=0;
 for(;cin>>Name;i++)
 {
     //cin>>Name;
  strcpy(s[i].name,Name);
  s[i].AC=0;
  s[i].penalty=0;
  for(int j=0;j<n;j++)
  {
   cin>>result;
   if(result[0]=='-'||result[0]=='0')//没通过 
   {
    continue;
   }
   s[i].AC++;
   int size=strlen(result);
   int k=0,count=0,time=0;
   for(;k<size;k++)
   {
    if(result[k]=='(') break;
    time=time*10+result[k]-'0';//计算用时 
   }
   k++;//注意这要先k++,不然‘(’也被计算 
  // cout<<"time "<<time <<endl;
   for(;k<size-1;k++)
   {
    if(result[k]==')') break;
    count=count*10+result[k]-'0';//计算错误次数 
   }
  // cout<<"count "<<count <<endl;
   s[i].penalty+=count*m+time;
  // cout<<"penalty "<<s[i].penalty<<endl;
  }
 }
 sort(s,s+i,cmp);//排序 
 for(int j=0;j<i;j++)
 {
  cout<<std::left<<setw(10)<<s[j].name<<" ";
  cout<<std::right<<setw(2)<<s[j].AC <<" ";
  cout<<std::right<<setw(4)<<s[j].penalty<<endl;
 }
 return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

rwyoi

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

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

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

打赏作者

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

抵扣说明:

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

余额充值