题目描述:
给定一场ACM比赛的题目数量和提交列表,请你打印输出最终榜单。榜单的格式见输出和样例。
根据比赛规则,榜单有以下要求:
每道题的通过罚时按照分钟计算。每次未通过提交增加20分钟罚时,输入数据保证每个队伍罚时均小于10000分钟。到比赛结束都没有通过的题目不计入该队伍的罚时。
每队通过后的题目在榜单的题目栏中用“+”号显示。如果仅提交一次就通过了,则显示“+”。否则显示“+k”,k 为这个队伍对于这道题通过之前的总提交次数。输入数据保证 k 不大于 9。
每队提交但是未通过的题目在榜单的题目栏中用“-”号显示。显示“-k”,k 为这个队伍对于这道题的总提交次数。输入数据保证 k 不大于9。
每队没有提交的题目需要在榜单的该队的题目栏留空。
题目提交状态为“Compile Error”的提交不计入榜单。
对于某个队伍,在通过某个题目后再次提交该题目,则通过后的提交不计入榜单。
如果某个队伍没有提交,或者所有的提交均不计入榜单。则榜单上不显示该队伍。
题目提交状态为“Accepted”的提交表示本题正确通过,其它状态均表示未通过。
输入描述:
第一行一个数字 n(n≤14),表示这场比赛有 n 道题目,题目的标号从 A开始。
接下来若干行,每行格式形如:时间 题号 结果 队名,表示一条提交记录,提交记录按提交时间顺序排列。
其中,时间形如HH:MM,输入数据保证时间一定小于05:00。
题号为单独的一个大写字母。
结果属于集合 { Accepted, Wrong Answer, Time Limit Exceeded, Compile Error, Memory Limit Exceeded, Output Limit Exceeded, Runtime Error, Presentation Error }。
队名为一个含有空格、大写和小写字母的字符串,队名长度不超过 43。
输入以一行 “GAME OVER!” 结尾,表示比赛结束。
输出描述:
输出的榜单有 n+4栏,每栏之间间隔 2个空格。
Rank一栏的宽度为 4个字符,表示该队伍的排名。
Who一栏的宽度43个字符,表示该队伍的名字。
Solved一栏宽度为 6个字符,显示每个队伍通过题目的数量。
Penalty一栏宽度为 7个字符,按要求显示每队总用时(每题通过时间+有效的总罚时)。
接下来是题目栏,每个题目栏的宽度均为 3个字符,按要求显示“+”或“-”,表示每个队伍通过题目的情况。
每一栏的第一行为这一栏的名称,其中,Who需左对齐,其他栏需右对齐。
题目栏的名称为题目的标号。
接下来若干行,按顺序输出每个队伍的信息,每栏的信息需右对齐。
队伍按照通过题目数量排名,如果两队通过题目数量相等,总用时少的队伍排名靠前。
如果出现题数和罚时均相等的队伍,则按照队名的字典序排序,同时Rank一栏的值需相等。第一个与他们排名不相等的队伍的排名选择绝对排名,例如前五个队伍的排名分别为1、2、3、3、3,则第六个队伍的绝对排名为6。
废话不多说,直接上代码:
代码一:
(自己所写代码)
//任务10(大作业)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct team
{
int rank;//该队伍的排名
char Who[43];//队伍名
int solved;//解题数
int Penalty;//队伍所用总时间
int time[14];//每道题解出的时间(分钟数)
int trys[14];//每道题解出之前尝试的次数
}Team;
Team teamArr[100];
int teamCount;//队伍的个数
int n;//题目的个数
//根据队伍名在teamArr中查找有没有出现过
//出现过返回对应下标
//没有出现返回-1
//循环查找上限由teamCount决定
int findTeam(char * teamStr)
{
int i;
for(i=0;i<teamCount;++i)
{
if(strstr(teamArr[i].Who,teamStr)!=NULL)
return i;
}
return -1;
}
int main(void)
{
int t,tim;
int i,j,a,b;
int in;
Team temp;
char str[100],team[100];
char * arr[8]={"Accepted"," Wrong Answer","Time Limit Exceeded",
"Compile Error","Memory Limit Exceeded",
"Output Limit Exceeded","Runtime Error",
"Presentation Error"};
scanf("%d",&n);
getchar();
for(gets(str);strstr(str,"GAME OVER!")==NULL;gets(str))
{
//int in;
if(str[1]-'5'==0) break;
tim=((str[0]-'0')*10+str[1]-'0')*60+(str[3]-'0')*10+(str[4]-'0');
t=str[6]-'A';
for(i=0;i<8;++i){
char *str1=str+8;
char *rtn=strstr(str,arr[i]);
if(rtn!=NULL) break;
}
if(str[8]-'W'==0)
strcpy(team,str+8+strlen(arr[i]));
else
strcpy(team,str+9+strlen(arr[i]));
if(i==3) continue;
//判断当前记录的队伍有没有在前面出现过
//若没有出现过则记录该队伍的名字
in=findTeam(team);
if(in ==-1){
in=teamCount++;
strcpy(teamArr[in].Who,team);
}
//teamArr[index];
if(str[8]-'A'==0) {
if(teamArr[in].time[t]!=0)
continue;
teamArr[in].solved ++;
teamArr[in].time[t]=tim;
}
else{
teamArr[in].trys[t]++;
}
}
//计算每支参赛队伍所用时间
for(i=0;i<teamCount;++i)
{
for(j=0;j<n;++j)
{
if(teamArr[i].time[j]!=0){
teamArr[i].Penalty+=teamArr[i].time[j];
teamArr[i].Penalty+=teamArr[i].trys[j]*20;
}
}
}
//针对解题数、时间、队伍名称对参赛队伍进行冒泡排序
for(i=0;i<teamCount-1;++i)
{
for(j=0;j<teamCount-1-i;++j)
{
if(teamArr[j].solved<teamArr[j+1].solved)
{
temp=teamArr[j];
teamArr[j]=teamArr[j+1];
teamArr[j+1]=temp;
}
else if(teamArr[j].solved==teamArr[j+1].solved)
{
if(teamArr[j+1].Penalty<teamArr[j].Penalty)
{
temp=teamArr[j];
teamArr[j]=teamArr[j+1];
teamArr[j+1]=temp;
}
else if(teamArr[j].Penalty==teamArr[j+1].Penalty)
{
if(strcmp(teamArr[j+1].Who,teamArr[j].Who)<0)
{
temp=teamArr[j];
teamArr[j]=teamArr[j+1];
teamArr[j+1]=temp;
}
}
}
}
}
//计算队伍排名
//解题数及时间都相同时排名相同
teamArr[0].rank=1;
for(a=1;a<teamCount;++a)
{
if(teamArr[a].solved==teamArr[a-1].solved && teamArr[a].Penalty==teamArr[a-1].Penalty)
teamArr[a].rank=teamArr[a-1].rank;
else
teamArr[a].rank=a+1;
}
//打印结果:
printf("Rank Who Solved Penalty ");
for(b=0;b<n;++b)
{
printf("%c ",b+'A');
}
printf("\n");
for(i=0;i<teamCount;++i)
{
printf("%4d",teamArr[i].rank);//结果正确
printf(" ");
printf("%43s",teamArr[i].Who);//结果正确
printf(" ");
printf("%6d",teamArr[i].solved);//结果正确
printf(" ");
printf("%7d",teamArr[i].Penalty);//结果正确
for(j=0;j<n;++j)
{
if(teamArr[i].trys[j]==0 && teamArr[i].time[j]!=0)
{
printf(" ");
printf("+");
}
else if(teamArr[i].trys[j]!=0 && teamArr[i].time[j]!=0)
{
printf(" ");
printf("+%d",teamArr[i].trys[j]);
}
else if(teamArr[i].trys[j]!=0 && teamArr[i].time[j]==0)
{
printf(" ");
printf("-%d",teamArr[i].trys[j]);
}
else
printf(" ");
}
printf("\n");
}
return 0;
}
代码二:
(参考答案代码)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct team {
char who[44]; // 队伍名称
int solved; // 解题数
int penalty; // 总用时
int title[14]; // 题目尝试次数
int titleState[14];// 题目状态 0未通过 1通过
} Team;
typedef struct node {
Team data;
struct node * next;
} Node;
// 题目数量
int n = 0;
// 提交记录状态数组
char * states[8] = {
"Accepted",
"Wrong Answer",
"Time Limit Exceeded",
"Compile Error",
"Memory Limit Exceeded",
"Output Limit Exceeded",
"Runtime Error",
"Presentation Error"
};
/**
* 链表中增加节点
* who : 队伍名
* return : 插入节点的地址
*/
Node * pushFrontList(Node ** pList, char * who) {
int i;
Node * newNode = (Node *)malloc(sizeof(Node));
strcpy(newNode->data.who, who);
newNode->data.solved = 0;
newNode->data.penalty = 0;
for(i=0; i<14; ++i) {
newNode->data.title[i] = 0;
newNode->data.titleState[i] = 0;
}
newNode->next = *pList;
*pList = newNode;
return newNode;
}
/**
* 链表中查找节点
* who : 队伍名
* return : 匹配节点的地址,没有找到返回NULL
*/
Node * findList(Node * list, char * who) {
for(; list!=NULL; list=list->next) {
if(strcmp(list->data.who, who)==0)
break;
}
return list;
}
/**
* 求链表节点个数
*/
int sizeList(Node * list) {
int n;
for(n=0; list!=NULL; ++n)
list = list->next;
return n;
}
/**
* 队伍比较,不存在
* return: 1 : t1>t2
* 0 : t1==t2
* -1 : t1<t2
*/
int cmpTeam(Team t1, Team t2) {
// 比较解题数
if(t1.solved > t2.solved)
return 1;
else if (t1.solved < t2.solved)
return -1;
// 解题数相等时,比较总用时
if(t1.penalty < t2.penalty)
return 1;
else if (t1.penalty > t2.penalty)
return -1;
// 解题数、总用时都相等
return 0;
}
/**
* 链表排序
*/
void sortList(Node * head) {
Team temp;
Node * p;
int cmprst;
int i, j;
int len = sizeList(head);
for(i=0; i<len-1; ++i) {
p = head;
for(j=0; j<len-i-1; ++j, p=p->next) {
// 比较解题数和总用时
cmprst = cmpTeam(p->data, p->next->data);
if(cmprst == 1)
continue;
// 比较队伍名称
if(cmprst==0 && strcmp(p->data.who, p->next->data.who) < 0)
continue;
// 交换
temp = p->data;
p->data = p->next->data;
p->next->data = temp;
}
}
}
/**
* 打印榜单
*/
void printBoard(Node * list) {
int i, j;
Node * head = list;
int len = sizeList(list);
int equFlag = 0;
// 打印榜单头
printf("%4s %-43s %6s %7s", "Rank", "Who", "Solved", "Penalty");
for(i=0; i<n; ++i)
printf(" %3c", 'A'+i);
printf("\n");
// 打印榜单内容
for(i=1; i<=len; ++i) {
int index = i;
if(equFlag != 0)
index = equFlag;
if(head->next!=NULL && cmpTeam(head->data, head->next->data) == 0)
equFlag = index;
else
equFlag = 0;
printf("%4d %-43s %6d %7d", index, head->data.who,
head->data.solved, head->data.penalty);
for(j=0; j<n; ++j) {
char str[4] = " ";
if(head->data.titleState[j]==1 && head->data.title[j]==0) {
str[2] = '+';
} else {
if(head->data.titleState[j]==1) {
str[1] = '+';
str[2] = head->data.title[j]+'0';
} else if(head->data.title[j] != 0) {
str[1] = '-';
str[2] = head->data.title[j]+'0';
}
}
printf(" %s", str);
}
printf("\n");
head = head->next;
}
}
int main(void) {
char str[100];
Node * list = NULL;
// 读取题目数量
scanf("%d", &n);
getchar();
// 循环读取提交记录
do {
int i, time, title, state;
char who[44];
Node * node;
gets(str);
if(strcmp(str, "GAME OVER!")==0)
break;
// 解析提交记录[时间]
time = (str[1]-'0')*60 + (str[3]-'0')*10 + (str[4]-'0');
// 解析提交记录[题目编号]
title = str[6]-'A';
// 解析提交记录[状态]
for(i=0; i<8; ++i) {
if(strstr(str+8, states[i])==(str+8)) {
state = i;
break;
}
}
// 状态为 "Compile Error" 不做任何处理
if(state == 3) {
continue;
}
// 获取提交记录[队伍名称]
strcpy(who, str+8+strlen(states[state])+1);
// 找到链表中队伍名称所对应节点
node = findList(list, who);
// 如果节点不存在,在链表中新增节点
if(node == NULL)
node = pushFrontList(&list, who);
if(state == 0) {
// 状态为 "Accepted"
if(node->data.titleState[title] == 1) {
// 当前提交记录对应题目已经解出,不做任何处理
continue;
}
// 题目状态改为已解出
node->data.titleState[title] = 1;
// 累加总用时
node->data.penalty += node->data.title[title] * 20 + time;
// 解题数+1
node->data.solved += 1;
} else {
// 其它状态,题目尝试次数+1
node->data.title[title] += 1;
}
} while(1);
// 链表排序
sortList(list);
// 打印榜单
printBoard(list);
return 0;
}