[code] PTA 胡凡算法笔记 DAY021

题目 A1083 List Grades

在这里插入图片描述

  • 题意
    按成绩排序,然后按排序顺序输出在成绩范围内[grade1, grade2]的学生信息。不存在的输出NONE

  • 思路
    这题和福布斯那题很像,主要就是写个cmp排序函数,然后识别成绩范围输出。这里需要注意的就是没有的情况,需要输出NONE(全大写)。

  • Code in C++

#include <cstdio>
#include <iostream>
#include <algorithm>

#define maxn 200

struct student {
    char name[11];
    char ID[11];
    int grade;
}stu[maxn];

bool cmp(const student &a, const student &b) {
    return a.grade > b.grade;
}

bool isValid(int grade, int grade1, int grade2) {
    if (grade >= grade1 && grade <= grade2) return true;
    else return false;
}

int main()
{
    int n;
    std::cin >> n;
    for (int i = 0; i < n; ++i) {
        scanf("%s %s %d", stu[i].name, stu[i].ID, &stu[i].grade);
    }
    int grade1, grade2;
    std::cin >> grade1 >> grade2;
    std::sort(stu, stu + n, cmp);
    int count = 0;
    for (int i = 0; i < n; ++i) {
        if (isValid(stu[i].grade, grade1, grade2)) {
            if (count != 0) std::cout << std::endl;
            printf("%s %s", stu[i].name, stu[i].ID);
            ++count;
        }
    }
    if (count == 0)
        std::cout << "NONE";
    return 0;
}


题目 A1080 Graduate Admission

在这里插入图片描述

  • 题意
    每个学生可以报m个学校志愿,根据总成绩和考试成绩排序。从前往后录取。但是在有相同排名的情况下可以超出学校录取规定人数。最后输出每个学校的录取学生情况。没有的输出空行。

  • 思路
    这里主要实现了两个cmp函数,一个是按总成绩和考试成绩排序,另一个是按录取学校编号和学生编号升序排序。然后就是也有相同排名的情况,不过条件变成两个条件。另外通过结构体cur_quota实现相同排名可以超人数录取。count记录已录取人数,index记录上个录取学生的序号,这样可以判断在超人数的时候可不可以并列录取。这里总成绩我直接采取了求和没有除以2,因为不影响相对大小。

  • Code in C++

#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 40001

int n, m, k;
int quota[101];
struct cur_quota {
    int count = 0;   // 记录已录取学生人数
    int index = 0;   // 记录最后一个录取学生的下标,便于比较是否存在同排名
}cur[101];

struct applicant {
    int num;
    int gradee;
    int gradei;
    int total;
    int school[5];
    int rank;
    int admmit;
}apps[maxn];

bool cmp(const applicant &a, const applicant &b) {
    if (a.total != b.total) return a.total > b.total;
    else return a.gradee > b.gradee;
}

bool cmps(const applicant &a, const applicant &b) {
    if (a.admmit != b.admmit) return a.admmit < b.admmit;
    else return a.num < b.num;
}

void init()
{
    for (int i = 0; i < n; ++i) {
        apps[i].num = i;
        apps[i].total = 0;
        memset(apps[i].school, -1, sizeof(apps[i].school));
        apps[i].rank = -1;
        apps[i].admmit = 100; // 因为学校最大为100,在后面学校排序时没有录取的排在后面
    }
}

int main()
{
    scanf("%d %d %d", &n, &m, &k);
    for (int i = 0; i < m; ++i) {
        scanf("%d", &quota[i]);
    }
    init();
    for (int i = 0; i < n; ++i) {
        scanf("%d %d", &apps[i].gradee, &apps[i].gradei);
        apps[i].total = apps[i].gradee + apps[i].gradei;
        for (int j = 0; j < k; ++j) {
            scanf("%d", &apps[i].school[j]);
        }
    }

    std::sort(apps, apps + n, cmp); // 按总成绩和gradee排序
    int r = 0;
    for (int i = 0; i < n; ++i) {
        if (i > 0 && (apps[i].total != apps[i-1].total || apps[i].gradee != apps[i-1].gradee)) {
            r = i;
        }
        apps[i].rank = r;
        for (int j = 0; j < k; ++j) {
            int num = apps[i].school[j];
            // 人数已达上限并且不存在与已录取学生同排名的情况下,进行下一个选项判断
            if (cur[num].count >= quota[num] && apps[(cur[num].index)].rank < apps[i].rank) {
                continue;
            } else {
                apps[i].admmit = num;
                ++cur[num].count;
                cur[num].index = i;
                break;
            }
        }
    }
    std::sort(apps, apps + n, cmps);  // 按学校和学生编号排序
    int start = 0;
    for (int i = 0; i < m; ++i) {
        if (cur[i].count == 0) {
            printf("\n");
        } else {
            printf("%d", apps[start].num);
            for (int j = 1; j < cur[i].count; ++j) {
                printf(" %d", apps[start + j].num);
            }
            start += cur[i].count;  // 存储下一个学校输出的学生首编号
            printf("\n");
        }
    }
    return 0;
}


小结

感觉这几天刷的内容都差不多,根据不同的规定实现不同的cmp函数。可能存在需要实现多个的情况,以及在实现完排序函数之后再加一些限制的情况。但总体来说没太大不同。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值