【B-测评系统】排名问题

题意:

例如某次考试一共八道题(A,B,C,D,E,F,G,H),每个人做的题都在对应的题号下有个数量标记:-3表示该学生在该题上有3次错误提交次数但还没AC,1表示AC的耗时,40(3) 表示该学生AC这道题耗时40,错误提交了3次。一共n道题,单位罚时为m。根据这些学生的得分,输出一个实时排名。采用多关键字排序,第一按AC题数,多的在前;第二按按时间分,少的在前;第三按名字的字典序,小的在前。输出时每个学生占一行,输出名字(10个字符宽),做出的题数(2个字符宽,右对齐)和时间分(4个字符宽,右对齐)。

样例输入:
在这里插入图片描述
样例输出:
在这里插入图片描述

思路:

首先从屏幕上读入每一个同学的数据,整理成所需的名字、AC题数、时间分。定义一个结构体info来存每个学生的信息,读入名字后因为知道题数所以循环读入数据,每次读入都进行处理,换算为AC题数和时间分,然后累加。

所有学生的数据都读完后,整理后的信息也存在了结构体数组中,根据多关键字,利用sort()函数进行排序。最后按照规定格式输出。

根据一个学生的数据算AC题数和时间分是解题关键。负数和0没有意义,本解法利用re_change()函数,把正数和带括号的数一起处理。找到括号前的数在字符串中的起始和终点位置[0,end),那么括号中的数是[end+1,strlen(s)-1),调用change()函数把字符串转化为整数。

总结:

因为读入数据时,数据与数据之间没有关联,所以采用边读入边换算的方法较好,还可以节省空间。

在cout输出时,如果限制字宽将默认右对齐,setiosflags(ios::left)可以设置左对齐。如果左右对齐交替输出,需要用resetiosflags(ios::left)解除左对齐,右对齐同理。

代码:

#include<iostream>
#include<string>
#include <algorithm>
#include<iomanip>
using namespace std;
struct info
{
	string name;
	int ti;
	int time;
};
bool com(info a, info b)
{
	if (a.ti != b.ti) return a.ti > b.ti;
	else if (a.time != b.time) return a.time < b.time;
	else return a.name[0] < b.name[0];
}
int change(string a, int begin, int end)//把字符串从[begin,end)变为数字 
{
	int re = 0;
	for (int i = begin; i < end; i++)
		re = re * 10 + a[i] - 48;
	return re;
}
int re_change(string s,int t)//把字符串变为数字
{
	int len = s.size();
	int begin = 0;//用时开始 
	int end = len;//用时结束、罚时开始 
	for (int k = 0; k < len; k++)
	{
		if (s[k] == 40)
		{
			end = k;
			break;
		}
	}
	int yt = change(s, begin, end);//用时
	if (end != len)
	{
		int ft = change(s, end + 1, len - 1);//罚时 
		return yt + ft * t;
	}
	else
		return yt;
}
int main()
{
	int n, t;
	cin >> n;
	cin >> t;
	int di = 0;
	info everyone[1000];//存储整理后的信息	
	while (cin >> everyone[di].name)
	{
		int tis = 0;
		int sum = 0;
		for (int i = 0; i < n; i++)
		{
			string score;
			cin >> score;
			if (score[0] == '-' || score[0] == 48)
				continue;
			else
			{
				tis++;
				sum = sum + re_change(score, t);
			}
			
		}
		everyone[di].ti = tis;
		everyone[di].time = sum;
		di++;
	}
	sort(everyone, everyone + di, com);
	for (int i = 0; i < di; i++)
		cout << setiosflags(ios::left) << setw(10) << everyone[i].name <<" "
		     << setiosflags(ios::right) << setw(2) << everyone[i].ti<<" "
		                                << setw(4) << everyone[i].time 
		                                << resetiosflags(ios::right)<< endl;
}

另一种解法:

(感觉没错,跑不过去也是很迷惑)

思路:

本解法按行读入,然后再根据空格分割字符串。其余处理字符串、排序等同上。

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include <algorithm> 
#define N 1000
using namespace std;
struct info
{
	char name[20];
	int ti;
	int time;
};
bool com(info a, info b)
{
	if (a.ti != b.ti) return a.ti > b.ti;
	else if (a.time != b.time) return a.time < b.time;
	else return a.name[0] < b.name[0];
}
int change(char* a,int begin,int end)//把字符串从[begin,end)变为数字 
{
	int re=0;
	for(int i=begin;i<end;i++)
		re=re*10+a[i]-48;
	return re;
}
int main()
{
	int n,t;
	scanf("%d", &n);
	scanf("%d", &t);
	getchar();
    char*str=new char[100];
	int i=0;
	info everyone[N];//存储整理后的信息	
	while (scanf("%[^\n]", str))
	{
		char** slipt =  new char*[n + 1];
		for (int j = 0; j < n + 1; j++)
			slipt[j] = new char[20];
		for (int j = 0; j < n + 1 ; j++)//分割字符串 
		{
			sscanf(str,"%s", slipt[j]);			
			char* pos2 = str + strlen(slipt[j]);//pos2是剩余的字符串
		    str=pos2;
			char* p=str;
			int len=0;
			//剩余字符串头有空格,需要去掉这些空格
			while (*p != '\0' && isspace(*p))
			{
				++p; 
				++len;
			}
			memmove(str, p, strlen(str) - len + 1); 
		}
		strcpy(everyone[i].name,slipt[0]);
		//计算时间
		int tis=0;
		int sum=0;
		for(int j=1;j<=n;j++)
		{
			if(slipt[j][0]=='-'||slipt[j][0]==48)
				continue;
			else
			{
				tis++;
				int len=strlen(slipt[j]);
				int begin=0;//用时开始 
				int end=len;//用时结束、罚时开始 
				for(int k=0;k<len;k++)
				{
					if(slipt[j][k]==40)
					{
						end=k;
						break;
					}					
				}
				int yt=change(slipt[j],begin,end);//用时
				if(end!=len)
				{
					int ft=change(slipt[j],end+1,len-1);//罚时 
					sum=sum+yt+ft*t;
				}
				else
					sum=sum+yt;	
			}
		}		
		everyone[i].ti=tis;
		everyone[i].time=sum;
		str[0] = '\0';
		getchar();
		i++;
		for (int j = 0; j < n + 1; j++)
			delete[]slipt[j];
	}
	sort(everyone, everyone + i, com);
	for(int ik=0;ik<i;ik++)
		printf("%-10s %2d %4d\n",everyone[ik].name,everyone[ik].ti,everyone[ik].time);	
}
发布了5 篇原创文章 · 获赞 4 · 访问量 97

猜你喜欢

转载自blog.csdn.net/qq_44047415/article/details/104657039
今日推荐