返回目录
题意
有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
注意点
- 最后输出时由于之前录取时进行了排序,这时需要输出原来的id
- 如果学校没有录取记录,则输出空行
#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;
}