考试排名
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 11564 Accepted Submission(s): 4097
Problem Description
C++编程考试使用的实时提交系统,具有即时获得成绩排名的特点。它的功能是怎么实现的呢?
我们做好了题目的解答,提交之后,要么“AC”,要么错误,不管怎样错法,总是给你记上一笔,表明你曾经有过一次错误提交,因而当你一旦提交该题“AC”后,就要与你算一算帐了,总共该题错误提交了几回。虽然你在题数上,大步地跃上了一个台阶,但是在耗时上要摊上你共花去的时间。特别是,曾经有过的错误提交,每次都要摊上一定的单位时间分。这样一来,你在做出的题数上,可能领先别人很多,但是,在做出同样题数的人群中,你可能会在耗时上处于排名的劣势。
例如:某次考试一共8题(A,B,C,D,E,F,G,H),每个人做的题都在对应的题号下有个数量标记,负数表示该学生在该题上有过的错误提交次数,但到现在还没有AC,正数表示AC所耗的时间,如果正数a跟上一对括号,里面有个整数b,那就表示该学生提交该题AC了,耗去了时间a,同时,曾经错误提交了b次,因此对于下述输入数据:
若每次错误提交的罚分为20分,则其排名从高到低应该是这样的:
Josephus 5 376
John 4 284
Alice 4 352
Smith 3 167
Bob 2 325
Bush 0 0
我们做好了题目的解答,提交之后,要么“AC”,要么错误,不管怎样错法,总是给你记上一笔,表明你曾经有过一次错误提交,因而当你一旦提交该题“AC”后,就要与你算一算帐了,总共该题错误提交了几回。虽然你在题数上,大步地跃上了一个台阶,但是在耗时上要摊上你共花去的时间。特别是,曾经有过的错误提交,每次都要摊上一定的单位时间分。这样一来,你在做出的题数上,可能领先别人很多,但是,在做出同样题数的人群中,你可能会在耗时上处于排名的劣势。
例如:某次考试一共8题(A,B,C,D,E,F,G,H),每个人做的题都在对应的题号下有个数量标记,负数表示该学生在该题上有过的错误提交次数,但到现在还没有AC,正数表示AC所耗的时间,如果正数a跟上一对括号,里面有个整数b,那就表示该学生提交该题AC了,耗去了时间a,同时,曾经错误提交了b次,因此对于下述输入数据:
![](https://i-blog.csdnimg.cn/blog_migrate/e5c680689e03cd8254ae7e912272956b.png)
若每次错误提交的罚分为20分,则其排名从高到低应该是这样的:
Josephus 5 376
John 4 284
Alice 4 352
Smith 3 167
Bob 2 325
Bush 0 0
Input
输入数据的第一行是考试题数n(1≤n≤12)以及单位罚分数m(10≤m≤20),每行数据描述一个学生的用户名(不多于10个字符的字串)以及对所有n道题的答题现状,其描述采用问题描述中的数量标记的格式,见上面的表格,提交次数总是小于100,AC所耗时间总是小于1000。
Output
将这些学生的考试现状,输出一个实时排名。实时排名显然先按AC题数的多少排,多的在前,再按时间分的多少排,少的在前,如果凑巧前两者都相等,则按名字的字典序排,小的在前。每个学生占一行,输出名字(10个字符宽),做出的题数(2个字符宽,右对齐)和时间分(4个字符宽,右对齐)。名字、题数和时间分相互之间有一个空格。
Sample Input
8 20 Smith -1 -16 8 0 0 120 39 0 John 116 -2 11 0 0 82 55(1) 0 Josephus 72(3) 126 10 -3 0 47 21(2) -2 Bush 0 -1 -8 0 0 0 0 0 Alice -2 67(2) 13 -1 0 133 79(1) -1 Bob 0 0 57(5) 0 0 168 -7 0
Sample Output
Josephus 5 376 John 4 284 Alice 4 352 Smith 3 167 Bob 2 325 Bush 0 0
好久之前就看到这题了一直没有去做,今天去做了;题目其实就是我们平时比赛的时候RANKLIST 上面的排名的成绩 ,题目其实很简单但是做的时候真的要被自己傻哭了;
这题其实就是个多级排序,用sort()函数或者 qsort()函数都是可以写的,可以去看下这个题目中的多级排序
点击打开链接
然后就是处理数据了,所有的数据都是要用字符数组去存。每个人都有做每道题题目的可能,所以有多少道题目就意味着每个人对应着多少道题目的成绩,可以是没有AC或者压根就没有做的,也可以是一次AC的和多次提交才AC的;
那么这里我们就可以开一个结构体,用结构体来存储每个人所对应的每题的成绩,那么操作就很简单了;
排序方面就是,第一级排序是按题目的多少来排,多的在前面,少的在后面(降序排序),一样的话就看他们AC的时间了,时间少的在前面,多的在后面(升序排序),如果还是一样就按他们的字典序排序(这个可以不用管的,因为都是正常的输入)
给出AC代码和注释;
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
struct NODE
{
char pro[200];
};
struct MODE
{
char name[20];
NODE pm[200];
int time = 0;
int count = 0;
int arry;
}people[1000];
int Wrong(char str[],int m,int k,int g)//做该题所需要的时间
{
int n = strlen(people[k].pm[g].pro);
int a;
int scoer = 0;
int flag = 0;
for (int i = 0; i < n; i++)
{
if (str[i] == '('){ flag = 1; a = i; break; }
}
if (flag == 0) //一次提交过的,直接记录AC时间就好了;
{
for (int i = 0; i < n; i++)
{
scoer = scoer * 10 + str[i] - '0';
}
}
else if (flag == 1)//提交AC了,但是之前也出现过WA,所以需要罚时
{
int s1 = 0;
for (int i = 0; i < a; i++)
{
s1 = s1 * 10 + str[i] - '0'; //提交过的时间
}
//cout << "s1=" << s1 << endl;
for (int i = a + 1; str[i] != ')'; i++)
{
scoer = scoer * 10 + str[i] - '0'; //罚的时间
}
//cout << "scoer=" << scoer << endl;
scoer = s1 + scoer * m;
}
return scoer;
}
bool Cmp(MODE a,MODE b)
{
if (a.count != b.count)return a.count > b.count; //首先按题目数量比较,如果相等则再按AC时间比较;
else return a.time < b.time;
}
int main()
{
int n, m;
while (~scanf("%d%d", &n, &m))
{
int k, i, j;
k = 0;
int x = 6;
while (~scanf("%s", people[k].name))
//while (x--)
{
//scanf("%s", people[k].name);//提交的时候居然忘记把这里注释掉了,导致一直WA;
for (i = 0; i < n; i++)
{
scanf("%s", people[k].pm[i].pro);
people[i].arry = i;
if (people[k].pm[i].pro[0] != '0'&&people[k].pm[i].pro[0] != '-')
{
people[k].count++;
//cout << Wrong(people[k].pm[i].pro, m) << endl;
people[k].time += Wrong(people[k].pm[i].pro, m,k,i);
}
}
k++;
}
sort(people, people + k, Cmp);//排序;
for (j = 0; j < k; j++)
{
printf("%-10s%3d%5d\n", people[j].name, people[j].count, people[j].time);//按题目要求控制输出格式
}
}
return 0;
}