【ACM】PAT.A1080 Graduate Admission【排序】

题目链接
题目分析

【学生排名规则】 1、平均分; 2、GE; 3、否则排名相同;

【录取规则】

  • 依 名次 从高往低 录取
  • 前一志愿满了 滑档 到后一志愿,全滑档则不录取
  • 同一排名的多人 报同一学校,即使该学校只有一个名额也要全录取
解题思路

并不难,按题意顺序写就行;注意录取细节。
1、结构体分别保存studentschool信息;
2、根据规则对student 结构体排序,并标记排名;
3、按学生排名,根据规则从高到低逐个录取


AC程序(C++)
/**************************
*@Author: 3stone
*@ACM: PAT.A1080 Graduate Admission
*@Time: 17/3/2
*@IDE: VS 2017
***************************/
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<set>

using namespace std;
#define maxn 40005

struct Student {
    int id; //初始编号
    int GE, GI, final_grade;  //成绩
    int app[8]; //志愿
    int rank; //排名
}stu[maxn];

struct School {
    int sch_quota; //招生定额
    int last_stu_admitted; //上一个招收学生的编号
    int num_admitted;  //招生人数
    set<int> stu_admitted; //招收学生的编号
}school[110];

bool cmp(Student s1, Student s2) {
    if (s1.final_grade != s2.final_grade)
        return s1.final_grade > s2.final_grade;
    else
        return s1.GE > s2.GE;
}


int main() {

    // 申请人数, 学校数,  最大志愿数
    int app_num, sch_num, cho_num;

    while(scanf("%d%d%d", &app_num, &sch_num, &cho_num) != EOF) {

        //输入 & 初始化
        for(int i = 0; i < sch_num; i++){
            scanf("%d", &school[i].sch_quota);
            school[i].num_admitted = 0;  //初始未招人
            school[i].last_stu_admitted = -1; //最后一个录取学生编号
        }
        for(int i = 0; i < app_num; i++){
            stu[i].id = i;
            scanf("%d%d", &stu[i].GE, &stu[i].GI);
            stu[i].final_grade = (stu[i].GE + stu[i].GI);
            for(int j = 0; j < cho_num; j++)
                scanf("%d", &stu[i].app[j]);
        }

        sort(stu, stu + app_num, cmp);

        //记录 排名
        for(int i = 0; i < app_num; i++){
            if(i > 0 && stu[i].final_grade == stu[i - 1].final_grade && stu[i].GE == stu[i - 1].GE)
                stu[i].rank = stu[i - 1].rank;
            else
                stu[i].rank = i;
            //printf("stu: %d %d %d\n", stu[i].id, stu[i].final_grade, stu[i].rank); //检查排名
        }

        //录取
        int cur_choice, last_stu;
        for(int i = 0; i < app_num; i++) { //按学生排名从高到低筛选
            for(int j = 0; j < cho_num; j++) { //按此学生的志愿依次筛选

                cur_choice = stu[i].app[j]; //当前志愿学校编号
                last_stu = school[cur_choice].last_stu_admitted; //此学校上一个招收的学生

                // 第一个判断条件:同名次都录取
                if (school[cur_choice].num_admitted < school[cur_choice].sch_quota 
                    || (last_stu != -1 && stu[last_stu].rank == stu[i].rank)){//还没录满,录取

                    school[cur_choice].num_admitted++;
                    school[cur_choice].last_stu_admitted = i;
                    school[cur_choice].stu_admitted.insert(stu[i].id);
                    break;
                }

            }
        }

        //输出 结果
        for(int i = 0; i < sch_num; i++){ //按学校编号

            if(school[i].num_admitted == 0){ //未录取
                printf("\n");
                continue;
            }
            //迭代器输出 录取学生编号
            set<int>::iterator set_end = school[i].stu_admitted.end();
            set<int>::iterator it = school[i].stu_admitted.begin();
            printf("%d", *it);
            for(++it; it != set_end; it++) {
                printf(" %d", *it);
            }
            printf("\n");
        }

    }//while-scanf

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值