PAT-A 1080 Graduate Admission (30 分)

1080 Graduate Admission (30 分)

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 G​E​​, and the interview grade G​I​​. The final grade of an applicant is (G​E​​+G​I​​)/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 G​E​​. 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 G​E​​ and G​I​​, 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

思路:坑点:注意每个学校都要输出一个换行符。

按照学生的总分和考试分数对所有学生进行排序,遍历所有学生,根据排名、志愿列表和学校的录取情况进行录取:

首先得到学生的总排名,然后遍历生的志愿列表,当发现当前志愿学校尚未招满,或者发现该学校招收的最后一个学生的排名和当前学生的排名相同,则将该考生录取到该志愿学校中。如果被当前志愿拒绝,再看下一个志愿。为了查看一个学校最后录取的学生名次,需要另外开一个数组记录该学校录取的最后一个学生的名次,每次录取新学生时更新该名次。

#include <algorithm>
#include <set>
#include <cstdio>

using namespace std;

typedef struct stu
{
    int id;//考生id,按照输入顺序确定
    int ge;//考试分数
    int gi;//面试分数
    int prefer[5];//志愿列表,最多5个
}stu;

bool cmp(stu a, stu b)
{   //按照考生的总分和考试分数进行排序
    if(a.ge + a.gi != b.ge + b.gi)
        return a.ge + a.gi > b.ge + b.gi;
    else
        return a.ge > b.ge;
}
int main()
{
    int n;//<=40000, the total number of applicants
    int m;//(≤100), the total number of graduate schools
    int k;//the number of choices an applicant may have.
    scanf("%d %d %d", &n, &m, &k);

    int quota[m];//i-th integer is the quota of the i-th graduate school respectively.
    for(int i = 0; i < m; i++)
        scanf("%d", quota + i);//输入学校的招生规模
    int admit[m] = {0};//已经录取的学生的数量
    int lastRank[m];//记录最后一个录取的考生的名次
    set<int> admittdStu[m];//记录每个学校已经录取的学生,set自动将学生排序

    //输入考试的成绩和志愿列表,序号自动成为id
    stu all[n];
    for(int i = 0; i < n; i++)
    {
        all[i].id = i;
        scanf("%d %d", &all[i].ge, &all[i].gi);//输入学生成绩
        for(int j = 0; j < k; j++)//输入学生的志愿列表
            scanf("%d", all[i].prefer + j);
    }

    sort(all, all + n, cmp);//按照总分和考试分数进行排序

    int nowRank;//当总分和考试分数都相同时,需要保持该名次
    for(int i = 0; i < n; i++)
    {
        //计算当前考生排名
        if(i == 0)
            nowRank = 0;
        else if(all[i].ge + all[i].gi < all[i - 1].ge + all[i - 1].gi)//总分比前一个考生低
            nowRank = i;
        else if(all[i].ge < all[i - 1].ge)//总分相同,但是考生成绩比前一个考生低
            nowRank = i;
        for(int j = 0; j < k; j++)
        {
            int school = all[i].prefer[j];//查看考生的当前志愿
            if(quota[school] > admit[school])//第一次写成了小于号,浪费了好多时间
            {//该学校尚未完成招生目标
                admit[school]++;//已录取人数加1
                lastRank[school] = nowRank;//最后一个录取的排名更新
                admittdStu[school].insert(all[i].id);//将新录取的学生录取到本学校中
                break;//成功录取,不再看下面的志愿
            }
            else if(nowRank == lastRank[school])//学校已经完成招生目标
            {   //题目没有要求输出学校实际招生人数,这里不再增加已录取人数
                admittdStu[school].insert(all[i].id);//将新录取的学生录取到本学校中
                break;//成功录取,不再看下面的志愿
            }
        }
    }
    for(int i = 0; i < m; i++)
    {
        for(auto it = admittdStu[i].begin(); it != admittdStu[i].end(); it++)
        {
            printf("%d", *it);
            auto temp = it;
            temp++;
            if(temp != admittdStu[i].end())
                printf(" ");
        }
        printf("\n");//这个换行符无论如何都要输出
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38127801/article/details/86493848