PAT.A1080 Graduate Admission

返回目录

在这里插入图片描述

题意

有N位考生,M所学校,每位考生都有K个志愿学校,每个学校也有招生人数限制。现在给出所有考生的初试成绩GE、面试成绩GI以及K个志愿学校的编号,要求模拟学校录取招生的过程,并输出每个学校录取的考生编号(按从小到大顺序)。下面是录取规则:
①先按考生的总分GE + GI从高到低排序,总分相同的按GE从高到低排序。如果GE仍然相同,则按排名相同处理。
②按排名先后来考虑每个考生最终录取的学校。对每个考生,按K个志愿的先后顺序考虑:如果当前志愿学校的已招生人数未达到该校的招生人数总额度,那么由该所学校录取他,并不再考虑该考生后面的志愿:如果当前志愿学校的已招生人数已达到招生人数总额度,但该校上一个录取考生的排名与该考生的排名相同,则可不受招生人数限制,由该学校破格录取他。除了上面两种情况,均视为该志愿学校无法录取该考生,转而考虑该考生的下一个志愿学校。如果该考生的所有志愿学校都无法录取该考生,则该考生彻底落榜。

样例(可复制)

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

样例输出

0 10
3
5 6 7
2 8

1 4

注意点

  1. 最后输出时由于之前录取时进行了排序,这时需要输出原来的id
  2. 如果学校没有录取记录,则输出空行
#include <bits/stdc++.h>
using namespace std;

struct student{
    int ge,gi,sum;
    int r,id;
    int cho[6];
}stu[40040];

struct school{
    int limit;
    int stunum;//当前已经招生人数
    int id[40010];
    int last;
}sch[110];

bool cmpstu(student a,student b){
    if(a.sum!=b.sum)return a.sum>b.sum;
    return a.ge>b.ge;
}
bool cmpid(int a,int b){
    return stu[a].id<stu[b].id;
}

int main(){
    int n,m,k;
    cin>>n>>m>>k;
    for(int i=0;i<m;i++){
        scanf("%d",&sch[i].limit);
        sch[i].stunum=0;
        sch[i].last=-1;
    }
    for(int i=0;i<n;i++){
        scanf("%d%d",&stu[i].ge,&stu[i].gi);
        stu[i].id=i;
        stu[i].sum=stu[i].ge+stu[i].gi;
        for(int j=0;j<k;j++){
            scanf("%d",&stu[i].cho[j]);
        }
    }
    sort(stu,stu+n,cmpstu);
    for(int i=0;i<n;i++){
        if(i>0&&stu[i].sum==stu[i-1].sum&&stu[i].ge==stu[i-1].ge)stu[i].r=stu[i-1].r;
        else stu[i].r=i;
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<k;j++){
            int choice=stu[i].cho[j];
            int num=sch[choice].stunum;
            int last=sch[choice].last;
            //如果学校还未招满或该考生与最后一个录取的人排名相同
            if(num<sch[choice].limit||(last!=-1&&stu[i].r==stu[last].r)){
                sch[choice].id[num]=i;
                sch[choice].last=i;
                sch[choice].stunum++;
                break;
            }
        }
    }
    for(int i=0;i<m;i++){
        if(sch[i].stunum>0){
            sort(sch[i].id,sch[i].id+sch[i].stunum,cmpid);
            for(int j=0;j<sch[i].stunum;j++){
                printf("%d",stu[sch[i].id[j]].id);
                if(j!=sch[i].stunum-1)printf(" ");
            }
        }
        printf("\n");
    }
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小怪兽会微笑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值