排序碎碎念(四):数据结构基础— PAT Judge

这道题我一开始是用C写的,但是自己写的用堆排序出了一点问题,我就换成了C++的sort函数,等我有空了,再去实现个完整的C语言版本吧。 - -

这道题我的思路是

1)结构体中不仅仅包含score[k],还要包含status[k],因为每一个题目都有四种状态,这四种状态有利于判断和输出。

#define NotSubmitted -1

#define CompileError 0

#define Submitted 2

#define SubmittedButGotZero 1


2)然后因为全部题目的状态都是 -1 或者 0,那么这个用户就不需要输出,所以在排序前,我使用Preprocess 这个函数让 L1 只存储需要输出的学生,再把L1 排序、打印。

3)最后一点需要注意的就是,在初始化的时候,记住 Max 函数无处不在啊,无论是对status函数score。

题目如下:10-排序5 PAT Judge(25 分)

The ranklist of PAT is generated from the status list, which shows the scores of the submissions. This time you are supposed to generate the ranklist for PAT.

Input Specification:

Each input file contains one test case. For each case, the first line contains 3 positive integers, N (104), the total number of users, K (5), the total number of problems, and M (105), the total number of submissions. It is then assumed that the user id's are 5-digit numbers from 00001 to N, and the problem id's are from 1 to K. The next line contains K positive integers p[i] (i=1, ..., K), where p[i] corresponds to the full mark of the i-th problem. Then M lines follow, each gives the information of a submission in the following format:

user_id problem_id partial_score_obtained

where partial_score_obtained is either −1 if the submission cannot even pass the compiler, or is an integer in the range [0, p[problem_id]]. All the numbers in a line are separated by a space.

Output Specification:

For each test case, you are supposed to output the ranklist in the following format:

rank user_id total_score s[1] ... s[K]

where rank is calculated according to the total_score, and all the users with the same total_score obtain the same rank; and s[i] is the partial score obtained for the i-th problem. If a user has never submitted a solution for a problem, then "-" must be printed at the corresponding position. If a user has submitted several solutions to solve one problem, then the highest score will be counted.

The ranklist must be printed in non-decreasing order of the ranks. For those who have the same rank, users must be sorted in nonincreasing order according to the number of perfectly solved problems. And if there is still a tie, then they must be printed in increasing order of their id's. For those who has never submitted any solution that can pass the compiler, or has never submitted any solution, they must NOT be shown on the ranklist. It is guaranteed that at least one user can be shown on the ranklist.

Sample Input:

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

Sample Output:

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

AC代码:

    //
    //  main.c
    //  PAT Judge
    //
    //  Created by air on 2018/5/12.
    //  Copyright © 2018年 air. All rights reserved.
#include <stdlib.h>
#include <iostream>
#include <stdbool.h>
#include <stdio.h>
#include <algorithm>
#define NotSubmitted -1
#define CompileError 0
#define Submitted 2
#define SubmittedButGotZero 1
using namespace std;
typedef int ScoreType;
typedef int IdType;
typedef int StatusType;
typedef struct Stu{
    IdType Id;
    ScoreType totalScore;
    ScoreType * Score;
    int numberOfPast;
    StatusType * Status;
}Student;
typedef Student* ptrToStudent;
typedef ptrToStudent List;

List Init(int N, int K, int M);
void Test(List L, int N, int K);
void Scan(List L, int N, int K);
bool cmpByIndex(Student a, Student b);
void print(List L, int i, int K);
ScoreType max( ScoreType a, ScoreType b );
int preProcess(List L, List L1, int N, int K);

ScoreType * fullScore;
/*------------ 一堆定义结束 ------------------*/
int main(int argc, const char * argv[]) {
    int N,K,M;
    scanf("%d %d %d\n", &N, &K, &M);
    
    List L = Init( N, K, M);
    //Test(L, N, K); //Init函数测试正确
    
        //排序之前做一个处理,把没有通过编译或者没有提交的剔除,所有题目的status都是 0 / -1 / 1 / 2
    List L1 = (List)malloc(sizeof(Student) * N);
    N = preProcess(L, L1, N, K);
    //printf("NEW N : %d", N);
    //Test(L1, N, K);
    
    sort(L1, L1 + N, cmpByIndex);
    //Test(L1, N, K); // 预处理后再排序!!
    
    Scan(L1, N, K); // 扫描函数正确
    return 0;
}


void Scan(List L, int N, int K){
    int oldNumber, count = 0, oldRank;
    oldRank = 0;
    oldNumber = L[N - 1].totalScore;
    
    for(int i = N - 1; i >= 0; i--){
        if(L[i].totalScore == -4)
            break;
        count ++;
        if(i == N-1){
            printf("%d %.05d %d ", oldRank + count, L[i].Id + 1, L[i].totalScore);
            print(L, i, K);
            continue;
        }
        if(L[i].totalScore != oldNumber){
            printf("%d %.05d %d ", oldRank + count, L[i].Id + 1, L[i].totalScore);
            print(L, i, K);
            oldRank = oldRank + count;
            count = 0;
        }else{
            printf("%d %.05d %d ", oldRank, L[i].Id + 1, L[i].totalScore);
            print(L, i, K);
        }
        oldNumber = L[i].totalScore;
    }
}

int preProcess(List L, List L1, int N, int K){
    int i,j;
    int len = 0;
    int flag = 0;
    
    for(int i = 0; i < N; i++){
        L1[i].Score = (ScoreType *)malloc(sizeof(ScoreType) * K);
        L1[i].Status = (StatusType *)malloc(sizeof(StatusType) * K);
        for(int j = 0; j < K; j++){
            L1[i].Score[j] = NotSubmitted;
            L1[i].Status[j] = NotSubmitted;
        }
    }
    
    
    for( i = 0 ; i < N; i++){
        for(j = 0; j < K; j++){
            if( !(L[i].Status[j] == 0 || L[i].Status[j] == -1))
                flag = 1;
        }
        if(flag == 1){
            L1[len].totalScore = L[i].totalScore;
            L1[len].numberOfPast = L[i].numberOfPast;
            L1[len].Id = L[i].Id;
            for(int a = 0; a < K; a++){
                L1[len].Score[a] = L[i].Score[a];
                L1[len].Status[a] = L[i].Status[a];
            }
            len++;
        }
        flag = 0;
    }
    
    return len;
}
/*------------进行排序------------------------------------------------------------------
 排序运算比较函数
 ------------------------------------------------------------------------------------------*/
bool cmpByIndex(Student a, Student b){
    //printf("%d  %d \n",a.Id, b.Id);
    if(a.totalScore < b.totalScore)
        return true;
    if((a.totalScore == b.totalScore) && (a.numberOfPast < b.numberOfPast))
        return true;
    if((a.totalScore ==b.totalScore) && (a.numberOfPast == b.numberOfPast) && (a.Id > b.Id) )
        return true;
    return false;
}

/*------------初始化学生表---------------------*/
List Init(int N, int K, int M){
    List L = (List)malloc(sizeof(Student) * N);
    /* 初始化 */
    for(int i = 0; i < N; i++){
        L[i].Score = (ScoreType *)malloc(sizeof(ScoreType) * K);
        L[i].Status = (StatusType *)malloc(sizeof(StatusType) * K);
        for(int j = 0; j < K; j++){
            L[i].Score[j] = NotSubmitted;
            L[i].Status[j] = NotSubmitted;
        }
        L[i].numberOfPast = 0;
        L[i].Id = i;
        L[i].totalScore = 0;
    }
    
    fullScore = (ScoreType *)malloc(sizeof(ScoreType) * K);
    for(int i = 0; i < K -1 ; i++)
        scanf("%d ", & fullScore[i]);
    scanf("%d\n", & fullScore[K - 1]);
    
    /* 初始学生的数据 */
    char strId[5];
    int id,NoOfProblem;
    ScoreType score;
    for(int i = 0; i < M; i++){
        scanf("%s %d %d\n", &strId, &NoOfProblem, &score );
        id = atoi(strId);//Need Test here!!!
        id --;
        NoOfProblem --;
        if((score == fullScore[NoOfProblem]) && ( L[id].Score[NoOfProblem] != fullScore[NoOfProblem] )){
            L[id].numberOfPast += 1;
        }
        
        if(score > 0){
            L[id].Status[NoOfProblem] = Submitted;
            L[id].Score[NoOfProblem] = max( L[id].Score[NoOfProblem], score );
        }
        
        if(score == 0){  //Compiler is Right, but get the score of zero
            L[id].Status[NoOfProblem] = max(SubmittedButGotZero, L[id].Status[NoOfProblem]);
            L[id].Score[NoOfProblem] = max( L[id].Score[NoOfProblem], score );
        }
        
        if(score == -1){
            L[id].Status[NoOfProblem] = max(CompileError, L[id].Status[NoOfProblem]);
            L[id].Score[NoOfProblem] = max( L[id].Score[NoOfProblem], CompileError );
        }
    }
    
    /* totalScore最后再额外的计算好了,不然重复提交还得又加又减 totalScore里面,编译未通过 和 得分为0还是两种不同的情况,得分别来考虑, 因为在输出的时候不一样 */
    for(int i = 0; i < N; i++){
        for(int j = 0; j < K; j++){
            if( L[i].Score[j]  != NotSubmitted)
                L[i].totalScore += L[i].Score[j];
        }
    }
    return L;
}

ScoreType max( ScoreType a, ScoreType b ){
    if (a > b)
        return a;
    else
        return b;
}
/*------------初始化学生表结束---------------------*/
void Test(List L, int N, int K){
    for(int i = 0; i < N; i++){
        printf("Student ID: %d\n",L[i].Id + 1);
        printf("Student totalScore: %d\n",L[i].totalScore);
        printf("Student Pass %d Problem\n", L[i].numberOfPast);
        for(int j = 0 ; j < K; j++)
            printf("Student ID :%d gets the score %d in Problem %d\n", L[i].Id, L[i].Score[j], j);
        printf("\n");
    }
}
/*------------自己写一个测试函数---------------------*/
void print(List L, int i, int K){
    for(int j = 0; j < K - 1; j++){
        if(L[i].Status[j] == -1)
            printf("- ");
        else
            printf("%d ",L[i].Score[j]);
    }
    if(L[i].Status[K - 1] == -1)
        printf("-\n");
    else
        printf("%d\n",L[i].Score[K - 1]);
}
/*------------针对题目成绩的输出函数---------------------*/





猜你喜欢

转载自blog.csdn.net/qq_25175067/article/details/80307037
今日推荐