B-评测系统

题目概述

例如某次考试一共八道题(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
8 20
GuGuDong  96     -3    40(3) 0    0    1      -8    0
hrz       107    67    -3    0    0    82     0     0
TT        120(3) 30    10(1) -3   0    47     21(2) -2
OMRailgun 0      -99   -8    0    -666 -10086 0     -9999996
yjq       -2     37(2) 13    -1   0    113(2) 79(1) -1
Zjm       0      0     57(5) 0    0    99(3)  -7    0
Sample Output
TT          5  348
yjq         4  342
GuGuDong    3  197
hrz         3  256
Zjm         2  316
OMRailgun   0    0

解题思路

1.由于此题需要多关键字排序,因此定义一个结构体Stu并重载比较操作。

2.定义字符数组score[]记录学生每道题的得分情况,时间分ac时间和罚时分别计算。ac时间:判断数组第一个元素,若不是’-‘也不是‘0’,那么一定是ac的题目,然后遍历字符串,把’('前的数字加起来(若有)。罚时:若有左括号,从左括号起遍历字符数组至右括号,把括号里的数字加起来。

3.最后用sort排序。

代码

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

//定义student结构体,并重写比较操作 
struct Stu{
 int a,b;//a为AC题数,b为时间 
 char name[10];
 bool operator< (const Stu &stu) const{
  if(a!=stu.a) return a>stu.a;
  if(b!=stu.b) return b<stu.b;
  return strcmp(name,stu.name)<0;//字典序升序 
 } 
}st[100005];

int n,m; //n为题数(1<=n<=12),m为单位罚时(10<=m<=20) 
int k=0; //k用于记录学生个数 
char score[1000];//存储学生每道题的得分情况 

int main()
{
 cin>>n>>m;
 while(~scanf("%10s",st[k].name))
 {
  st[k].a=0;
  st[k].b=0;
    for(int i=0;i<n;i++)
  {
   cin>>score;
   if(score[0]!='-'&&score[0]!='0')   
   {
    st[k].a++; //计算AC的题目个数 
    int label=0,num=0;
    for(int j=0;j<strlen(score);j++)
    {//此轮for循环计算ac时间 
     if(score[j]=='(')
     {
      label=j; //若有括号,label用于记录左括号的位置 
      break; 
     }
     num=num*10+score[j]-'0';//计算AC的时间 
    }
        st[k].b+=num; 
    num=0;
    if(label) 
    { 
     for(int j=label+1;j<strlen(score)-1;j++)
     {//此轮for循环计算罚时 
      num=num*10+score[j]-'0';
     }    
    }
    st[k].b+=num*m;
       }
  }
  k++;
  sort(st,st+k);  
 }
 for(int i=0;i<k;i++)
 {
  printf("%-10s %2d %4d\n",st[i].name,st[i].a,st[i].b);
 // cout<<setw(10)<<setfill(' ')<<st[i].name<<" "<<setw(2)<<setiosflags(ios::right)<<st[i].a<<" "<<setw(4)<<setiosflags(ios::right)<<st[i].b<<endl;
 }
 return 0;
} 

总结反思

1.关于格式化输出,只记得cout、setw了,怎么忘了printf%加宽度了呢!!正数默认右对齐,负数左对齐,记住了!!
2.这一题比较憨的点…:最终结果在循环里输出了!!核对样例时只顾看最后一组和样例一模一样,却没注意前面输出了n-1次…改到头秃也不知道错在哪…还好同学提醒了我,以后绝对不会再犯了…

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值