ZZULIOJ1198: 考试排名(二)(结构体专题)

1198: 考试排名(二)(结构体专题)

题目描述:
ACM 国际大学生程序设计竞赛,英文全称:ACM International Collegiate Programming Contest(ACM-ICPC 或 ICPC)是由美国计算机协会(ACM)主办的,一项旨在展示大学生创新能力、团队精神和在压力下编写程序、分析和解决问题能力的年度竞赛。经过30多年的发展,ACM 国际大学生程序设计竞赛已经发展成为最具影响力的大学生计算机竞赛。一般就简称为 ACM 竞赛了(虽然照理来说应该简称成 ICPC 才对)。
ACM 竞赛的计分规则如下:
首先按照过题数排名,过题数相同的队伍按照罚时排名(罚时小的队伍排在前面),如果罚时也相同则认为名次相同(名次相同时在排名表上队伍 id 较小的队伍列在前面)。
对于罚时的计算。队伍总体的罚时等于该队各题的罚时之和。对于某题的罚时,如果这道题最后没有通过(没有正确提交),则这题的罚时为 0,否则这道题的罚时为:从比赛开始到该题第一次正确提交经过的时间 + 第一次通过之前的错误提交次数 * 20 分钟。
例如:某次考试一共8题(A,B,C,D,E,F,G,H),每个人做的题都在对应的题号下有个数量标记,负数表示该学生在该题上有过的错误提交次数,但到现在还没有AC,正数表示AC所耗的时间,如果正数a跟上一对括号,里面有个整数b,那就表示该学生提交该题AC了,耗去了时间a,同时,曾经错误提交了b次,因此对于下述输入数据:

则其排名从高到低应该是这样的:
Josephus 5 376
John 4 284
Alice 4 352
Smith 3 167
Bob 2 325
Bush 0 0

输入:
输入数据的第一行是考试题数n(1≤n≤12),每行数据描述一个学生的用户名(不多于10个字符的字串)以及对所有n道题的答题现状,其描述采用问题描述中的数量标记的格式,见上面的表格,提交次数总是小于100,AC所耗时间总是小于1000。 参加考试的人数不超过100人。

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

样例输入:
8
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

样例输出:
Josephus 5 376
John 4 284
Alice 4 352
Smith 3 167
Bob 2 325
Bush 0 0

代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<ctype.h>	//包含字符串转换函数,下面读入每道题分数时使用的字符串,需要用到该函数
#define SWAP(a,b,t){t = a; a = b; b = t;}
/*ac是通过量,time是总时间,ret是每道题所消耗时间*/
typedef struct student{
	char name[11];
	int ac, time, ret[13];
}STU;

int Fatoi(char *s, char *p, STU a){
	char str[10];
	int j, k = 0, sum = 0;
	for(j = 0; s[j] != '('; j++){
		str[j] = s[j];
	}
	sum += atoi(str);
	memset(str,0,sizeof(str));
	for(j = 1; *(p+j) != ')'; j++){
		str[k++] = *(p+j);
	}
	str[k] = '\0';
	sum = sum + atoi(str)*20;
	return sum;
}
/**************************************************
这道题的主要思路如下:
1.循环读入name,再通过循环用字符串读入每道题消耗时间给s;
2.注意一下逻辑顺序:先判断该题是否完成;若完成,需要判断
是否存在罚时(带括号);
3.尽量让主函数代码简单易懂,便于逻辑的建立;
**************************************************/
int main()
{
	int n, i = 0, t, j;
	char *p;		//这里的指针用于题目完成时,是否存在括号的判断
	scanf("%d",&n);
	STU a[101], temp;
	char s[10];
	while(scanf("%s",a[i].name) != EOF){
		a[i].ac = 0;
		a[i].time = 0;
		memset(s,0,sizeof(s));
		for(t = 0; t < n; t++){
			scanf("%s",s);
			/*题目未完成时*/
			if(s[0] == '0' || s[0] == '-'){
				a[i].ret[t] = 0;
				continue;
			}
			/*题目完成时*/
			else if(isdigit(s[0]) && s[0] != '0'){
				a[i].ac ++;
				p = NULL;
				p = strchr(s,'(');
				/*当存在括号时,指针p的地址是'('的地址,
				若不存在时,指针p为空*/
				if(p == NULL)
					a[i].ret[t] = atoi(s);
				else
					a[i].ret[t] = Fatoi(s,p,a[i]);
				a[i].time += a[i].ret[t];
			}
		}
		i++;
	}
	/*用冒泡循环来排序*/
	for(j = 0; j < i-1; j++){
		for(t = j+1; t < i; t++){
			if(a[j].ac < a[t].ac)
				SWAP(a[j],a[t],temp)
			else if(a[j].ac == a[t].ac){
				if(a[j].time > a[t].time)
					SWAP(a[j],a[t],temp)
				else if(a[j].time == a[t].time){
					if(strcmp(a[j].name,a[t].name) > 0)
						SWAP(a[j],a[t],temp)
				}
			}
		}
	}
	for(j =0; j < i; j++)
		printf("%-10s %2d %4d\n",a[j].name,a[j].ac,a[j].time);
	return 0;
}

总结反思:
1.当需要复杂判断的时候尽量让主函数简单明了,突出逻辑,在子函数中处理单一判断便于后期检查问题;
2.不清楚字符串状态,可以用memset(s,0,sizeof(s));来清零;
3.交换排序时也可以定义一个函数,让主函数更简单。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值