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;
}

编译结果:

1015

版本三: 为考生添加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);
    }
}

posted @ 2017-10-17 14:34  阿胜4K  阅读(336)  评论(0编辑  收藏  举报