C语言1015. 德才论 (25)

原题: https://www.patest.cn/contests/pat-b-practise/1015

题意:
输入格式:
输入第1履让闹3只刚整数,分别吗:
N(<=105),即考生总数;
L(>=60),为用最低分数线,即德分和才分开都无低于L的考生才发身份被考虑录用;
H(<100),为先行录取线
1类似,
德分和才分开都无小于此线之于定义为“才德全尽”,此类考生按照德才总分从大至没有排序;
2接近, 才分开不交可德分到线的均等好像考生属于“德胜才”,也随总分排序
3像样, 德才分开都低于H,但是德分不小于才分开
4接近, 其他达到最低线L的考生为以总分排序,但排在第三好像考生之后。

思路分析:
N<=10万, 考生总数
L>=60, 最低录取线
H优先录取线
倘若no, rp, sk, sum, level分别代表同样各项考生的学号, 德分, 才分, 总分,
类别
逐行读入考生信息, rp < low || sk < low的考生, 去掉.
而外及格, 4类考生还亟需满足的原则是
第1类, rp >= H && sk >= H
第2类, rp >= H && sk < H
第3类, rp < H && sk < H && rp >= sk
第4类, 非以上3中情况

读入学生信息, 根据规则分学生添加上对应之level, 之后进行相同破排序.
排序需要先看level, 再看sum, rp, no. 版本3如约这种艺术实现.

本一样: 直接动用冒泡排序, 会出现逾期现象不克AC

#include <stdio.h>
#include <stdlib.h>

struct students {
    long int no; //学号
    int rp; // 德分
    int sk; // 才分
    int sum; // 总分
};
typedef struct students s_stu;

void print (s_stu *stu, int len);
void sort (s_stu *stu, int len);
void swap (s_stu *stu, int i, int j);

int main () {
    s_stu *allStu;   // 所有达到录取线的学生信息
    s_stu *stuType1; // 第1类学生
    s_stu *stuType2; // 第2类学生
    s_stu *stuType3; // 第3类学生
    s_stu *stuType4; // 第4类学生
    int len1 = 0; // 1类学生总数
    int len2 = 0; // 2类学生总数
    int len3 = 0; // 3类学生总数
    int len4 = 0; // 4类学生总数
    int pass = 0;  // 达到最低录取线学生总数
    int total; // 考生总数
    int low; // 最低录取分数线
    int high; // 优先录取分数线
    s_stu temp; // 临时存放读入学生信息
    int i;
    int i1 = 0;
    int i2 = 0;
    int i3 = 0;
    int i4 = 0;

    scanf("%d", &total);
    scanf("%d", &low);
    scanf("%d", &high);

    // 动态学生数组内存分配
    allStu = (s_stu*)malloc(sizeof(s_stu) * (total + 1));

    // 读入学生信息, 并对学生分类
    // 按照个人编程习惯, 数组下标0, 不存东西
    for (i=1; i<=total; i++) {
        scanf("%ld", &temp.no); //学号
        scanf("%d", &temp.rp); // 德分
        scanf("%d", &temp.sk); // 才分
        temp.sum = temp.rp + temp.sk; // 总分

        // 低于最低录取线, 先排除
        if (temp.rp < low || temp.sk < low) {
            continue;
        }
        pass++;
        allStu[pass] = temp; // 所有达到录取线的学生信息
        if (temp.rp >= high && temp.sk >= high) {
        // 1类学生
            len1++;
        } else if (temp.rp >= high && temp.sk < high) {
        // 2类学生
            len2++;
        } else if (temp.rp < high && temp.sk < high
            && temp.rp >= temp.sk) {
        // 3类学生
            len3++;
        } else {
        // 4类学生
            len4++;
        }
    }

    // 动态为4种类型的学生分配空间
    // 为了节省内存只能这么麻烦了, 不然用链表的话
    // 代码量至少2倍
    stuType1 = (s_stu*)malloc(sizeof(s_stu) * (len1 + 1));
    stuType2 = (s_stu*)malloc(sizeof(s_stu) * (len2 + 1));
    stuType3 = (s_stu*)malloc(sizeof(s_stu) * (len3 + 1));
    stuType4 = (s_stu*)malloc(sizeof(s_stu) * (len4 + 1));

    // 为4类学生分别赋值
    for (i=1; i<=pass; i++) {
        if (allStu[i].rp >= high && allStu[i].sk >= high) {
        // 1类学生
            i1++;
            stuType1[i1] = allStu[i];
        } else if (allStu[i].rp >= high && allStu[i].sk < high) {
        // 2类学生
            i2++;
            stuType2[i2] = allStu[i];
        } else if (allStu[i].rp < high && allStu[i].sk < high
            && allStu[i].rp >= allStu[i].sk) {
        // 3类学生
            i3++;
            stuType3[i3] = allStu[i];
        } else {
        // 4类学生
            i4++;
            stuType4[i4] = allStu[i];
        }
    }
    free(allStu); // 达标学生信息用不上了

    // 对4类学生分别进行排序
    sort(stuType1, len1);
    sort(stuType2, len2);
    sort(stuType3, len3);
    sort(stuType4, len4);

    // 分别打印4类学生的信息
    printf("%d\n", len1 + len2 + len3 + len4);
    print(stuType1, len1);
    print(stuType2, len2);
    print(stuType3, len3);
    print(stuType4, len4);

    return 0;
}

// 打印学生信息
// 参数: stu[], 学生数组, len, 学生长度
void print (s_stu *stu, int len) {
    int i;
    if (len == 0) {
        // 根据题意, 如果该类学生为空则 do nothing
        //printf("该类型学生信息为空\n");
    } else {
        for (i=1; i<=len; i++) {
            printf("%ld %d %d\n", stu[i].no, stu[i].rp, stu[i].sk);
        }
    }
}

/*
对结构体进行排序
排序要参考3个条件
1. 总分高, 排在上面
2. 总分相等并且德分高, 排在上面
3. 总分相等并且德分也相等, 准考证号小的排在上面
参数: stu, 要排序的学生数组, len, 该类型学生的实际个数
*/
void sort (s_stu *stu, int len) {
    int i;
    int j;
    for (i=1; i<=len; i++) {
        for (j=len; j>i; j--) {
            if (stu[j].sum > stu[j-1].sum) {
                swap(stu, j, j-1);
            }
            if (stu[j].sum == stu[j-1].sum
                && stu[j].rp > stu[j-1].rp) {
                swap(stu, j, j-1);
            }
            if (stu[j].sum == stu[j-1].sum
                && stu[j].rp == stu[j-1].rp
                && stu[j].no < stu[j-1].no) {
                swap(stu, j, j-1);
            }
        }
    }
}

// 交换结构体数组
// 功能: 对stu[i] 和 stu[j] 进行交换
void swap (s_stu *stu, int i, int j) {
    s_stu temp;
    temp = stu[i];
    stu[i] = stu[j];
    stu[j] = temp;
}

/*
input:
14 60 80
10000001 64 90
10000002 90 60
10000011 85 80
10000003 85 80
10000004 80 85
10000005 82 77
10000006 83 76
10000007 90 78
10000008 75 79
10000009 59 90
10000010 88 45
10000012 80 100
10000013 90 99
10000014 66 60

output:
12
10000013 90 99
10000012 80 100
10000003 85 80
10000011 85 80
10000004 80 85

10000007 90 78
10000006 83 76
10000005 82 77
10000002 90 60

10000014 66 60

10000008 75 79
10000001 64 90
*/

本子2: 改用C语言自带的飞跃排序qsort, 能够AC

#include <stdio.h>
#include <stdlib.h>

struct students {
    long int no; //学号
    int rp; // 德分
    int sk; // 才分
    int sum; // 总分
};
typedef struct students s_stu;

void print (s_stu *stu, int len);
int compare(const void *a, const void *b); // qsort 排序函数

int main () {
    s_stu *allStu;   // 所有达到录取线的学生信息
    s_stu *stuType1; // 第1类学生
    s_stu *stuType2; // 第2类学生
    s_stu *stuType3; // 第3类学生
    s_stu *stuType4; // 第4类学生
    int len1 = 0; // 1类学生总数
    int len2 = 0; // 2类学生总数
    int len3 = 0; // 3类学生总数
    int len4 = 0; // 4类学生总数
    int pass = 0;  // 达到最低录取线学生总数
    int total; // 考生总数
    int low; // 最低录取分数线
    int high; // 优先录取分数线
    s_stu temp; // 临时存放读入学生信息
    int i;
    int i1 = 0;
    int i2 = 0;
    int i3 = 0;
    int i4 = 0;

    scanf("%d", &total);
    scanf("%d", &low);
    scanf("%d", &high);

    // 动态学生数组内存分配
    allStu = (s_stu*)malloc(sizeof(s_stu) * (total + 1));

    // 读入学生信息, 并对学生分类
    // 按照个人编程习惯, 数组下标0, 不存东西
    for (i=1; i<=total; i++) {
        scanf("%ld", &temp.no); //学号
        scanf("%d", &temp.rp); // 德分
        scanf("%d", &temp.sk); // 才分
        temp.sum = temp.rp + temp.sk; // 总分

        // 低于最低录取线, 先排除
        if (temp.rp < low || temp.sk < low) {
            continue;
        }
        pass++;
        allStu[pass] = temp; // 所有达到录取线的学生信息
        if (temp.rp >= high && temp.sk >= high) {
        // 1类学生
            len1++;
        } else if (temp.rp >= high && temp.sk < high) {
        // 2类学生
            len2++;
        } else if (temp.rp < high && temp.sk < high
            && temp.rp >= temp.sk) {
        // 3类学生
            len3++;
        } else {
        // 4类学生
            len4++;
        }
    }

    // 动态为4种类型的学生分配空间
    // 为了节省内存只能这么麻烦了, 不然用链表的话
    // 代码量至少2倍
    stuType1 = (s_stu*)malloc(sizeof(s_stu) * (len1 + 1));
    stuType2 = (s_stu*)malloc(sizeof(s_stu) * (len2 + 1));
    stuType3 = (s_stu*)malloc(sizeof(s_stu) * (len3 + 1));
    stuType4 = (s_stu*)malloc(sizeof(s_stu) * (len4 + 1));

    // 为4类学生分别赋值
    for (i=1; i<=pass; i++) {
        if (allStu[i].rp >= high && allStu[i].sk >= high) {
        // 1类学生
            i1++;
            stuType1[i1] = allStu[i];
        } else if (allStu[i].rp >= high && allStu[i].sk < high) {
        // 2类学生
            i2++;
            stuType2[i2] = allStu[i];
        } else if (allStu[i].rp < high && allStu[i].sk < high
            && allStu[i].rp >= allStu[i].sk) {
        // 3类学生
            i3++;
            stuType3[i3] = allStu[i];
        } else {
        // 4类学生
            i4++;
            stuType4[i4] = allStu[i];
        }
    }
    free(allStu); // 达标学生信息用不上了

    // 对4类学生分别进行排序
    // 下标0, 填充最大值, 以免妨碍排序
    // 已经写到这了, 其实再重写一次我会考虑下标0用上
    stuType1[0].no = 66666666;
    stuType1[0].rp = 200;
    stuType1[0].sk = 200;
    stuType1[0].sum = 400;

    stuType2[0].no = 66666666;
    stuType2[0].rp = 200;
    stuType2[0].sk = 200;
    stuType2[0].sum = 400;

    stuType3[0].no = 66666666;
    stuType3[0].rp = 200;
    stuType3[0].sk = 200;
    stuType3[0].sum = 400;

    stuType4[0].no = 66666666;
    stuType4[0].rp = 200;
    stuType4[0].sk = 200;
    stuType4[0].sum = 400;
    // 用C语言自带快速排序, qsort进行排序
    qsort(stuType1, len1+1, sizeof(s_stu), compare);
    qsort(stuType2, len2+1, sizeof(s_stu), compare);
    qsort(stuType3, len3+1, sizeof(s_stu), compare);
    qsort(stuType4, len4+1, sizeof(s_stu), compare);

    // 分别打印4类学生的信息
    printf("%d\n", len1 + len2 + len3 + len4);
    print(stuType1, len1);
    print(stuType2, len2);
    print(stuType3, len3);
    print(stuType4, len4);

    return 0;
}

// 打印学生信息
// 参数: stu[], 学生数组, len, 学生长度
void print (s_stu *stu, int len) {
    int i;
    if (len == 0) {
        // 根据题意, 如果该类学生为空则 do nothing
        //printf("该类型学生信息为空\n");
    } else {
        for (i=1; i<=len; i++) {
            printf("%ld %d %d\n", stu[i].no, stu[i].rp, stu[i].sk);
        }
    }
}

/*
对结构体进行排序
排序要参考3个条件
1. 总分高, 排在上面
2. 总分相等并且德分高, 排在上面
3. 总分相等并且德分也相等, 准考证号小的排在上面
分析:
arg1 > arg2 && res > 0, 排序后arg1在arg2右边(arg2, arg1)
*/
int compare(const void *a, const void *b) {
    int res;
    s_stu stu1 = *(s_stu*)a;
    s_stu stu2 = *(s_stu*)b;

    if (stu1.sum > stu2.sum) {
        res = -1;
    } else if (stu1.sum < stu2.sum) {
        res = 1;
    }

    if (stu1.sum == stu2.sum) {
        if (stu1.rp > stu2.rp) {
            res = -1;
        }
        if (stu1.rp < stu2.rp) {
            res = 1;
        }

        if (stu1.rp == stu2.rp) {
            if (stu1.no > stu2.no) {
                res = 1;
            }
            if (stu1.no < stu2.no) {
                res = -1;
            }
        }
    }
    return res;
}

编译结果:

C语言 1

本三: 为考生添加level以区分类别 AC

#include <stdio.h>
#include <stdlib.h>

struct student {
    long int no;
    int rp;
    int sk;
    int level;
};
typedef struct student s_stu;

void print (s_stu stu[], int len);
int compare (const void *a, const void *b);

int main () {
    int total;
    int low;
    int high;
    int len = 0;
    s_stu temp;
    int i;

    scanf("%d", &total);
    scanf("%d", &low);
    scanf("%d", &high);
    s_stu stu[total];

    for (i=0; i<total; i++) {
        scanf("%ld", &temp.no);
        scanf("%d", &temp.rp);
        scanf("%d", &temp.sk);
        if (temp.rp < low || temp.sk < low) {
            continue;
        }
        if (temp.rp >= high && temp.sk >= high) {
            temp.level = 1;
        } else if (temp.rp >= high && temp.sk < high) {
            temp.level = 2;
        } else if (temp.rp < high && temp.sk < high
            && temp.rp >= temp.sk) {
            temp.level = 3;
        } else {
            temp.level = 4;
        }
        stu[len] = temp;
        len = len + 1;
    }

    qsort(stu, len, sizeof(s_stu), compare);
    print(stu, len);

    return 0;
}

int compare (const void *a, const void *b) {
    s_stu stu1 = *((const s_stu*)a);
    s_stu stu2 = *((const s_stu*)b);
    int res;
    int sum1 = stu1.rp + stu1.sk;
    int sum2 = stu2.rp + stu2.sk;

    if (stu1.level > stu2.level) res = 1;
    if (stu1.level < stu2.level) res = -1;
    if (stu1.level == stu2.level) {
        res == 0;
        if (sum1 > sum2) res = -1;
        if (sum1 < sum2) res = 1;
        if (sum1 == sum2) {
            if (stu1.rp > stu2.rp) res = -1;
            if (stu1.rp < stu2.rp) res = 1;
            if (stu1.rp == stu2.rp) {
                if (stu1.no > stu2.no) res = 1;
                if (stu1.no < stu2.no) res = -1;
            }
        }
    }

    return res; // MD, 忘记个return, 用了我3h+, 才解决 WTF
}

void print (s_stu stu[], int len) {
    int i;

    printf("%d\n", len);
    for (i=0; i<len; i++) {
        printf("%ld %d %d\n", stu[i].no, stu[i].rp, stu[i].sk);
    }
}