69,565
社区成员
发帖
与我相关
我的任务
分享
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define MaxUsers 10001
typedef struct Stu{
int id;
int total;
int score[5];
int full;
} List[MaxUsers];
int read( int table[], List stu, int full_score[], int p_num, int m );
void Shell_Sort( int table[], List stu, int n);
int Check( int table[], List stu, int tmp, int tmpid, int j, int d );
void Init( List stu, int id, int p_num );
//int compare( const void *a, const void *b );
int main()
{
int n, k, m, i, j, real_user;
List stu;
scanf("%d %d %d", &n, &k, &m);
int full_score[k]; //记录题目满分
for ( i=0; i<k; ++i )
scanf("%d", &full_score[i]);
int table[n]; //table记录需要显示的用户数,后面排序只需对table进行排序即可
for ( i=0; i<n; ++i )
table[i] = -1;
//开始读数据,读完返回需要显示的用户数
real_user = read(table, stu, full_score, k, m);
// qsort(table, real_user, sizeof(int), compare); //对table进行快速排序
Shell_Sort(table, stu, real_user); //对table进行希尔排序
//以下按序输出table中的用户
int last;
for ( i=0; i<real_user; ++i )
{
int tmp = table[i];
if ( i == 0 )
{
printf("%d ", i+1);
last = i+1;
}
else{
if ( stu[tmp].total == stu[table[i-1]].total )
printf("%d ", last);
else{
printf("%d ", i+1);
last = i+1;
}
}
printf("%05d %d", tmp, stu[tmp].total);
for ( j=0; j<k; ++j )
{
if ( stu[tmp].score[j] != -1 )
printf(" %d", stu[tmp].score[j]);
else
printf(" -");
}
if ( i!=real_user-1 )
printf("\n");
}
return 0;
}
void Shell_Sort( int table[], List stu, int n)
{
int i, j, d, k = 0;
int tmp, tmpno;
while (pow(2, k)-1<n)
++k;
--k; //使用Hibbard增量序列
for( ; k>=1; --k )
{
d = pow(2,k)-1;
for ( i=d; i<n; ++i )
{
tmp = stu[table[i]].total; //tmp记录当前用户的总分
tmpid = table[i]; //tmpid记录当前用户的id
for ( j=i; j>=d && Check(table, stu, tmp, tmpid, j, d); j-=d )
{
table[j] = table[j-d];
}
table[j] = tmpno;
}
}
}
int Check( int table[], List stu, int tmp, int tmpid, int j, int d )
{
if ( tmp > stu[table[j-d]].total ) //总分比较
return 1;
else if ( tmp == stu[table[j-d]].total )
{
if ( stu[table[j]].full > stu[table[j-d]].full ) //满分科目比较
return 1;
else if ( stu[table[j]].full == stu[table[j-d]].full )
{
if ( tmpid < table[j-d] ) //id大小比较
return 1;
}
}
return 0;
}
void Init( List stu, int id, int p_num ) //初始化当前序号的stu结构
{
int i;
stu[id].total = 0;
stu[id].full = 0;
for ( i=0; i<p_num; ++i )
stu[id].score[i] = -1;
}
int read( int table[], List stu, int full_score[], int p_num, int m )
{
int id, no, score, flag; //cnt用来记录table数组的移动,用于返回需要显示的用户数
int i, j, k, cnt = -1; //record数组记录当前用户状态
int record[10001]; //record[id] == 0说明当前用户并未有过任何操作
for ( i=0; i<10001; ++i) //record[id] == 1说明当前用户已经满足显示排名的条件
record[i] = 0; //record[id] == 2说明当前用户有过编译记录但是均未通过
for ( i=0; i<m; ++i )
{
scanf("%d %d %d", &id, &no, &score);
if ( !record[id] ) //如果该用户从未编译过
{
Init(stu, id, p_num); //初始化该用户的结构,其中每题分数均记录为-1
if ( score == -1 ){ //如果编译失败
stu[id].score[no-1] = -2; //将该门分数记录为-2以便后续处理
record[id] = 2; //更改状态为有过编译记录但是均未通过
}
else{ //如果编译成功
stu[id].total = score; //总分更改
stu[id].score[no-1] = score; //该门分数值更改
if ( full_score[no-1] == score )//若满分则满分数加一
++stu[id].full;
table[++cnt] = id; //需要显示的用户数加一
record[id] = 1; //更改状态为需要显示
}
}
else if ( record[id] == 1 ) { //如果该用户状态为已经记录为需要显示的
if ( score == -1 ) //如果此次编译失败,将分数记为0
++score;
if ( score > stu[id].score[no-1] ) //如果这次分数大于上次的分数
{
if ( stu[id].score[no-1] == -1 )//若该题从未编译过,直接将分数改为0
stu[id].score[no-1] = 0;
stu[id].total += (score-stu[id].score[no-1]);//总分加等于这次提交分数减掉原来分数
stu[id].score[no-1] = score; //该题成绩更改
if ( full_score[no-1] == score )//若满分则满分数加一
++stu[id].full;
}
}
else if ( record[id] == 2 ) { //若该用户状态为提交过编译但均失败
if ( score == -1 ) //如果这次提交也编译失败
{
stu[id].score[no-1] = -2; //则本次提交打上编译失败的标记
}
else { //如果这次提交成功了(编译通过)
for ( k=0; k<p_num; ++k ) //将之前所有被打上编译失败的题目均置为0分
if ( stu[id].score[k] == -2 )
stu[id].score[k] == 0;
table[++cnt] = id; //在table表上记录该用户
record[id] = 1; //该用户状态置为需要显示的
stu[id].total = score; //总分置为此次提交的分数
stu[id].score[no-1] = score; //该题分数更新
}
}
}
return cnt+1; //返回table中记录的用户数,即最终显示的用户数
}
else if ( record[id] == 2 ) { //若该用户状态为提交过编译但均失败
if ( score == -1 ) //如果这次提交也编译失败
{
stu[id].score[no-1] = -2; //则本次提交打上编译失败的标记
}
else { //如果这次提交成功了(编译通过)
for ( k=0; k<p_num; ++k ) //将之前所有被打上编译失败的题目均置为0分
if ( stu[id].score[k] == -2 )
stu[id].score[k] == 0;
table[++cnt] = id; //在table表上记录该用户
record[id] = 1; //该用户状态置为需要显示的
if ( full_score[no-1] == score )//若满分则满分数加一
++stu[id].full;
stu[id].total = score; //总分置为此次提交的分数
stu[id].score[no-1] = score; //该题分数更新
}
}