SDU--B - 爆零(×)大力出奇迹(√)

题目描述

程序设计思维作业和实验使用的实时评测系统,具有及时获得成绩排名的特点,那它的功能是怎么实现的呢?
我们千辛万苦怼完了不忍直视的程序并提交以后,评测系统要么返回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);
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值