题目描述
程序设计思维作业和实验使用的实时评测系统,具有及时获得成绩排名的特点,那它的功能是怎么实现的呢?
我们千辛万苦怼完了不忍直视的程序并提交以后,评测系统要么返回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个字符宽,右对齐)。名字、题数和时间分相互之间有一个空格。数据保证可按要求的输出格式进行输出。 |
样例输入
样例输出
思路
综述
排序的规则:
1、先按照过题数目排序,过题多的排在前面;
2、再按照用时多少排序,用时少的排在前面;
用时计算规则,共有四种状态:
1)0,该题未提交过,不记录时间;
2)负数,表示提交过多次出错,不记录时间;
3)一个正数,表示过题,计时为该正数;
4)一个正数加一个括号里面是一个正数,计时为第一个正数再加第二个正数乘以罚时单位的积;
3、按照名字的字典序排序;
对于多关键字排序的题目,可以构造结构体P,重载小于号,再构造优先队列priority_queue<P>,从而达到排序的目的;
过程
结构体:
struct P {
string name;//名字
int score;//罚时
int ac;//过题数目
operator <(const P &p)const{
if(ac!=p.ac) return ac<p.ac;
if(score!=p.score) return score>p.score;
return name>p.name;
}
};
step1:
接收题目数量和单位罚时
cin>>n>>m;
step2:
因为不知道学生数目所以采用如下
while(cin>>stu.name)
step3:
对每个学生进行计算:
step3.1:初始化
stu.ac=0;
stu.score=0;
step3.2:
接收到该学生的某道题的答题情况,用string接收
string s1;
cin>>s1;
进入字符串流
stringstream ss;
ss<<s1;
接收第一个数字
ss>>num1;
并且进行判断
1)没有罚时也没有过题
if(num1<=0) continue;
2)x是char类型,用于接收后来的左括号‘(’,然后对学生的记录进行更新,即:
过题数目++
罚时+=num1+num2*单位罚时
ss>>x;
ss>>num2;
stu.ac++;
stu.score+=num1;
stu.score+=num2*m;
总结
输出格式问题:
printf:
printf("%4d",ss.score);//占四位,右对齐
printf("%-5d",ss.score);//占五位,左对齐
cout:
cout<<setiosflags(ios::left)<<setw(10)<<ss.name;//占十位,左对齐
cout<<setiosflags(ios::right)<<setw(9)<<ss.name;//占九位,右对齐
代码
#include <bits/stdc++.h>
#include <stdio.h>
#include <iomanip>
using namespace std;
struct P {
string name;//名字
int score;//罚时
int ac;//过题数目
operator <(const P &p)const{
if(ac!=p.ac) return ac<p.ac;
if(score!=p.score) return score>p.score;
return name>p.name;
}
};
int main(){
priority_queue<P> heap;
int n,m,i,j;
cin>>n>>m;
struct P stu;
while(cin>>stu.name){
stu.ac=0;
stu.score=0;
for(j=0;j<n;j++){
stringstream ss;
string s1;
cin>>s1;
int num1,num2,num3;
char x;
num1 = num2 = 0;
ss<<s1;
// 接收第一个数字
ss>>num1;
// 没过该题
if(num1<=0) continue;
else{
// 接收左括号
ss>>x;
// 接收第二个数字
ss>>num2;
stu.ac++;
stu.score+=num1;
stu.score+=num2*m;
}
}
heap.push(stu);
}
//输出
while(!heap.empty()){
struct P ss;
ss = heap.top();
heap.pop();
cout<<setiosflags(ios::left)<<setw(10)<<ss.name;
cout<<" ";
printf("%2d %4d\n",ss.ac,ss.score);
}
}