(c语言详解)10-排序5 PAT Judge (详细解释)

本博文源于浙江大学《数据结构》,今天跟随姥姥做习题,发现此题是真的繁琐,比统计工龄繁杂n倍(统计工龄我已附上链接),不过再难也要理出头绪,下面给出具体的细节分析
(c语言详解)10-排序4 统计工龄(简洁版详细解释)

原文(翻译)如下:

PAT的ranklist是由状态列表生成的,其中显示了提交的分数。这一次,您应该为PAT生成ranklist。

输入规格:

每个输入文件包含一个测试用例。对于每种情况,第一行包含3个正整数,N(≤104),用户总数,K(≤5),问题总数,M(≤10^5),以及提交作品的总数。然后假设用户id是从00001到N的5位数字,而问题id是从1到K的。下一行包含K个正整数p[i] (i=1,…,其中p[i]对应第i个问题的满分。接下来是M行,每一行都给出了一个提交的信息,格式如下:

user_id problem_id partial_score_obtained

其中partial_score_为- 1(如果提交甚至不能通过编译器),或者为[0,p[problem_id]]范围内的整数。一行中的所有数字都用空格隔开。

输出规范:

对于每个测试用例,您应该按照以下格式输出ranklist:

user_id total_score s[1]…s [K]

其中根据total_score计算rank,具有相同total_score的所有用户获得相同的rank;s[i]是第i个问题得到的部分分数。如果用户从未提交过问题的解决方案,则必须在相应位置打印“-”。如果用户为解决一个问题提交了多个解决方案,那么将计算最高分。

ranklist必须按秩的非递减顺序打印。对于具有相同级别的用户,必须根据完美解决的问题的数量按非递增顺序排序。如果仍然有领带,则必须按其id的递增顺序打印。对于那些从来没有提交过任何可以通过编译器的解决方案的人,或者从来没有提交过任何解决方案的人,他们不能显示在ranklist上。可以保证至少有一个用户可以显示在ranklist上。

样例输入:

7 4 20
20 25 25 30
00002 2 12
00007 4 17
00005 1 19
00007 2 25
00005 1 20
00002 2 2
00005 1 15
00001 1 18
00004 3 25
00002 2 25
00005 3 22
00006 4 -1
00001 2 18
00002 1 20
00004 1 15
00002 4 18
00001 3 4
00001 4 2
00005 2 -1
00004 2 0

样例输出:

1 00002 63 20 25 - 18
2 00005 42 20 0 22 -
2 00007 42 - 25 - 17
2 00001 42 18 18 42
5 00004 40 15 0 25 -

分析输入输出

输入第一行

第一个参数 用户的个数
第二个参数 问题的个数
第三个参数 记录的个数

输入第二行

四个问题的分别总分

输入第三行起

第一个参数用户id,第几个问题 该用户的得分
其中-1表示未编译通过,0表示编程错误有分

输出

第一个参数名次
第二个参数 用户编号
第三个参数 用户四道题目总分
第四个参数起各个题目用户的相应得分

破题关键

为用户建立结构体,结构体存储用户信息,然后根据读取,为用户信息进行更新,最后来个表排序,最后按照格式输出用户信息即可。看起来我说的非常顺畅那么怎么实现呢?

read函数

主要将信息读入,这个函数任务先做简单的初始化,比如未提交,用户存在但没分数的你做最后比较如何标记,你都可以在初始化帮他们设定,比如我,未曾回答设个值,如果回答了,直接将值跟新。还有你每次提交是不是要跟新这个值,最后为他们统计个总分,这全部都可以在read函数实现

compare函数

给分数做排序有个关键是为总分排序,而不是为每道题目排序,因此这个compare函数是定义排序规则,在这里排序的规则是总分咯,设定一下

ShellSort函数

希尔排序或者其他排序都行,最主要的把compare函数调用进去,在这里未实现copy,而是做了简单的表排序,如果大家表排序不知道,可以看这篇博主写的文章
(C语言浙大版)小白实现表排序含基本原理(附测试用例)
仅作非物理排序,这是最简单的。况且希尔排序的增量序列,也仅仅是选择排序的升级版本。

main函数

读入第一行得数据,开始准备活动做好,然后调用相应的函数,先read函数调用好,然后调用排序函数,最后为了格式安全,输出用户信息,然后开始提交。

附上源码

//px-1-2.c
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
typedef struct {
	int eachpro[6];
	int total;
	int perfect;
}Score;

int N,K,M;
int fullmark[6];

void Read(Score * sro)
{
	int i,j,id,num,mark,flag;
	for(i=0;i<N;++i) {
		for(j=1;j<=K;++j) 
			sro[i].eachpro[j] = -2; //表示未曾回答,-1为通过
		sro[i].total = 0;
		sro[i].perfect = 0;
	}
	
	for(i=0;i<M;++i) {
		scanf("%d %d %d",&id,&num,&mark);
		if(sro[id-1].eachpro[num]<mark)
			sro[id-1].eachpro[num] = mark;
	}
	for(i=0;i<N;++i) {
		flag = 1;
		for(j=1;j<=K;++j) {
			if(sro[i].eachpro[j]>=0) {
				flag = 0;
				sro[i].total += sro[i].eachpro[j];
				if(sro[i].eachpro[j] == fullmark[j])
					sro[i].perfect++;
			}
		}
		if(flag)
			sro[i].total = -1;
	}
	
}

int Compare(Score *sro,int a,int b) {
	if(sro[a].total > sro[b].total)
		return 1;
	else if(sro[a].total<sro[b].total)
		return 0;
	else {
		if(sro[a].perfect>sro[b].perfect)
			return 1;
		else if(sro[a].perfect<sro[b].perfect)
			return 0;
		else {
			if(a<b)
				return 1;
			else 
				return 0;
		}
	}
}

void ShellSort(Score *sro,int *index) {
	int i,j,k,d,t;
	for(k=log10(N+1)/log10(2);k>0;--k) {
		d = pow(2,k)-1;
		for(i=d;i<N;++i) {
			t = index[i];
			for(j=i;j>=d&&Compare(sro,t,index[j-d]);j-=d)
				index[j] = index[j-d];
			index[j] = t;
		}
	}
}

int main()
{
    scanf("%d %d %d",&N,&K,&M);
    int i;
    for(i=1;i<=K;++i)
        scanf("%d",&fullmark[i]);
    Score* sro=(Score*)malloc(N*sizeof(Score));
    Read(sro);
    int* index=(int*)malloc(N*sizeof(int));
    for(i=0;i<N;++i)
        index[i]=i;
    ShellSort(sro,index);
    int cur,j;
    for(i=0;i<N;++i){//输出结果
        if(sro[index[i]].total==-1)
            break;
        if(!i||(i>0&&sro[index[i]].total!=sro[index[i-1]].total)){//与前一用户的总分不同,则按实际排名输出
            printf("%d ",i+1);
            cur=i+1;//最新用户排名
        }else
            printf("%d ",cur);//与前一用户总分相同,则按前一用户的排名输出
        printf("%05d ",index[i]+1);
        printf("%d ",sro[index[i]].total);
        for(j=1;j<=K;++j){
            if(sro[index[i]].eachpro[j]==-2)//未被回答过
                printf("-");
            else if(sro[index[i]].eachpro[j]==-1)//未通过编译
                printf("0");
            else
                printf("%d",sro[index[i]].eachpro[j]);
            if(j!=K)
                printf(" ");
            else
                printf("\n");
        }
    }
    return 0;
}



版权声明:本文为m0_37149062原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。