【PAT甲级 - C++题解】1080 Graduate Admission

✍个人博客:https://blog.csdn.net/Newin2020?spm=1011.2415.3001.5343
📚专栏地址:PAT题解集合
📝原题地址:题目详情 - 1080 Graduate Admission (pintia.cn)
🔑中文翻译:研究生入学
📣专栏定位:为想考甲级PAT的小伙伴整理常考算法题解,祝大家都能取得满分!
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪

1080 Graduate Admission

It is said that in 2011, there are about 100 graduate schools ready to proceed over 40,000 applications in Zhejiang Province. It would help a lot if you could write a program to automate the admission procedure.

Each applicant will have to provide two grades: the national entrance exam grade GE, and the interview grade GI. The final grade of an applicant is (GE+GI)/2. The admission rules are:

  • The applicants are ranked according to their final grades, and will be admitted one by one from the top of the rank list.
  • If there is a tied final grade, the applicants will be ranked according to their national entrance exam grade GE. If still tied, their ranks must be the same.
  • Each applicant may have K choices and the admission will be done according to his/her choices: if according to the rank list, it is one’s turn to be admitted; and if the quota of one’s most preferred shcool is not exceeded, then one will be admitted to this school, or one’s other choices will be considered one by one in order. If one gets rejected by all of preferred schools, then this unfortunate applicant will be rejected.
  • If there is a tied rank, and if the corresponding applicants are applying to the same school, then that school must admit all the applicants with the same rank, even if its quota will be exceeded.

Input Specification:

Each input file contains one test case.

Each case starts with a line containing three positive integers: N (≤40,000), the total number of applicants; M (≤100), the total number of graduate schools; and K (≤5), the number of choices an applicant may have.

In the next line, separated by a space, there are M positive integers. The i-th integer is the quota of the i-th graduate school respectively.

Then N lines follow, each contains 2+K integers separated by a space. The first 2 integers are the applicant’s GE and GI, respectively. The next K integers represent the preferred schools. For the sake of simplicity, we assume that the schools are numbered from 0 to M−1, and the applicants are numbered from 0 to N−1.

Output Specification:

For each test case you should output the admission results for all the graduate schools. The results of each school must occupy a line, which contains the applicants’ numbers that school admits. The numbers must be in increasing order and be separated by a space. There must be no extra space at the end of each line. If no applicant is admitted by a school, you must output an empty line correspondingly.

Sample Input:

11 6 3
2 1 2 2 2 3
100 100 0 1 2
60 60 2 3 5
100 90 0 3 4
90 100 1 2 0
90 90 5 1 3
80 90 1 0 2
80 80 0 1 2
80 80 0 1 2
80 70 1 3 2
70 80 1 2 3
100 100 0 2 4

Sample Output:

0 10
3
5 6 7
2 8

1 4
题意

需要写个程序来处理学生的入学申请书,每个学生都会提供两个成绩:全国入学考试成绩 GE 和面试成绩 GI

而录取的规则如下:

  • 申请者将根据其最终成绩由高到低进行排名,并且将从排名列表的顶部开始逐一录取。
  • 如果申请者的最终成绩并列,则按照 GE 成绩由高到低进行排名,如果成绩仍然并列,则并列者的排名必须相同。
  • 每个申请人可以填报 K 个志愿,并且将根据他/她的志愿进行录取:如果按照排名列表,轮到某位学生被录取了,并且其第一志愿学校还未招满人,则他成功被该学校录取。如果名额已满,则按顺序考虑其他志愿,直至成功被录取为止。如果所有报名学校都无法录取该名学生,则该名学生录取失败。
  • 如果出现并列排名,并且并列申请人正在申请同一所学校,那么该学校不得只录取其中一部分申请人,即使超过招生限额,也必须全部录取。
思路

按照题意进行模拟,具体思路如下:

  1. 用一个结构体来存储学生的所有信息,并且重载比较和等于运算符用于后续的排序。
  2. 输入学校和学生的信息,并对学生的成绩按规则排序,成绩越高的同学越有优先权选择学校。
  3. 从前往后遍历排序后的学生数组,越在数组前面的同学成绩越高,每次遍历都找出成绩相同的那部分学生,因为题目规定如果成绩并列且学生志愿相同,即使志愿的学校名额加上这些同学后会超额也必须全部录取进来。为了实现该功能,会用一个临时的 wish 数组来保存每个学生的志愿,先根据名额数是否超限找出每个学生最终的录取情况,最后再统一更新到答案数组中。
  4. 打印录取结果,每个学校的打印结果要按照录取学生编号升序排序,并且行末不得有空格,如果该学校没有录取的学生,则打印空行。
代码
#include<bits/stdc++.h>
using namespace std;

const int N = 40010, M = 110, K = 5;
int n, m, k;
int wish[N];
int cnt[M];
vector<int> uty[M];

//定义学生结构体
struct Person
{
    int id, ge, gi;
    int wish[K];

    //返回成绩之和
    int total()const
    {
        return ge + gi;
    }

    //重载比较运算符
    bool operator<(const Person& t)const
    {
        if (total() != t.total())  return total() > t.total();
        else    return ge > t.ge;
    }

    //重载等于运算符
    bool operator==(const Person& t)const
    {
        return ge == t.ge && gi == t.gi;
    }
}p[N];

int main()
{
    scanf("%d%d%d", &n, &m, &k);

    //输入学校和学生的信息
    for (int i = 0; i < m; i++)    scanf("%d", &cnt[i]);
    for (int i = 0; i < n; i++)
    {
        p[i].id = i;
        scanf("%d%d", &p[i].ge, &p[i].gi);
        for (int j = 0; j < k; j++)    scanf("%d", &p[i].wish[j]);
    }

    //对学生成绩进行排序,成绩高的同学优先选择学校
    sort(p, p + n);

    //初始化临时存储志愿信息的数组
    memset(wish, -1, sizeof wish);

    //开始计算录取情况
    for (int i = 0; i < n;)
    {
        //找出成绩相同的同学
        int j = i + 1;
        while (j < n && p[i] == p[j])  j++;

        //为每个人分配学校
        for (int t = i; t < j; t++)
            for (int u = 0; u < k; u++)
            {
                int w = p[t].wish[u];
                //判断名额是否已经超额
                if (cnt[w] > uty[w].size())
                {
                    wish[t] = w;
                    break;
                }
            }

        //将分配结果更新到结果数组
        for (int t = i; t < j; t++)
            if (wish[t] != -1)
                uty[wish[t]].push_back(p[t].id);

        //更新指针
        i = j;
    }

    //打印录取结果
    for (int i = 0; i < m; i++)
    {
        if (uty[i].size() > 0)
        {
            //需按照编号升序排序
            sort(uty[i].begin(), uty[i].end());
            printf("%d", uty[i][0]);
            for (int j = 1; j < uty[i].size(); j++)
                printf(" %d", uty[i][j]);
        }
        puts("");
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值