简要阐述:
在解决问题的时候,经常会有一些排序问题。一般采用冒泡排序、插入排序,或者利用sort函数排序
就能解决。但是遇到多关键字的排序,自己写排序算法就可能会挺麻烦的,这里就要利用sort函数。
多关键字排序中sort()函数和结构体的使用:
1、在结构体中重载比较符" < ":
struct node{
int a,b,c;
bool operator < (const node &n) const{
if(a!=n.a) return a>n.a;//第一关键字降序
if(b!=n.b) return b<n.b;//第二关键字升序
return c>n.c;//第三关键字降序
}
};
2.定义sort函数中的cmp:
bool cmp(const node &n1,const node &n2)
{
if(n1.a!=n2.a) return n1.a>n2.a;//第一关键字降序
if(n1.b!=n2.b) return n1.b<n2.b;//第二关键字升序
return n1.c>n2.c;//第三关键字降序
}
//使用sort(node_array,node_array+n,cmp) 就可以对数组node_array排序。
3.结合lambda匿名函数使用,直接在sort()里面写lambda函数:
sort(node_array,node_array+n,[](node &n1,node &n2)->bool{
if(n1.a!=n2.a) return n1.a>n2.a;//第一关键字降序
if(n1.b!=n2.b) return n1.b<n2.b;//第二关键字升序
return n1.c>n2.c;//第三关键字降序
};
具体问题:
例如某次考试一共八道题(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个字符宽,右对齐)。名字、题数和时间分相互之间有一个空格。数据保证可按要求的输出格式进行输出。
8 20
GuGuDong 96 -3 40(3) 0 0 1 -8 0
hrz 107 67 -3 0 0 82 0 0
TT 120(3) 30 10(1) -3 0 47 21(2) -2
OMRailgun 0 -99 -8 0 -666 -10086 0 -9999996
yjq -2 37(2) 13 -1 0 113(2) 79(1) -1
Zjm 0 0 57(5) 0 0 99(3) -7 0
问题分析:
1.首先是多关键字排序:
第一关键字:AC题数,降序排序
第二关键字:时间(罚时多少),升序排序
第三关键字:名字字典排序,升序排序。
2.然后就是 12(30) 这样的形式如何分开成两个数字读入。
这里介绍一个sscanf()函数,用法和scanf()差不多,只不过读入的是字符串。
char score[20];
scanf(“%s”,score);
int t,f;
int res=sscanf(score,”%d(%d)”,&t,&f);
这样,第一个数字读入t,第二个数字读入f。
res=1表示只有一个数字;res=2表示有两个数字。
所有代码
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
struct person
{
char na[20];
int sum_count;
int penalty;
}a[10000];
bool cmp(const person &a,const person &b)
{
if(a.sum_count!=b.sum_count)
return a.sum_count>b.sum_count;
if(a.penalty!=b.penalty)
return a.penalty<b.penalty;
return strcmp(a.na,b.na)<0;
}
int main()
{
int T,pe,count,sum_pe,time[2],flag;
scanf("%d %d",&T,&pe);
int renshu=0;
while(scanf("%s",a[renshu].na)!=EOF)
{
count=0;
sum_pe=0;
for(int i=0;i<T;i++)
{
char score[20];
scanf("%s",score);
int t,f;
int res=sscanf(score,"%d(%d)",&t,&f);
if(res==2)//如果读取到两个数
{
count++;
sum_pe=sum_pe+t+f*pe;
}
else if(res==1)//如果读取到一个数
{
if(t>0)
{
count++;
sum_pe=sum_pe+t;
}
}
}
a[renshu].penalty=sum_pe;
a[renshu].sum_count=count;
renshu++;
}
sort(a,a+renshu,cmp);
for(int i=0;i<renshu;i++)
{
printf("%-10s %2d %4d\n",a[i].na,a[i].sum_count,a[i].penalty);
}
return 0;
}