题意:
根据学生的成绩和排名,根据学校的招生情况,确定最终的招生结果。
输入N,M,K,代表N个学生,M个学校,每个学生有K种志愿(可以相同)
接下来的一行输入M个整数,代表这M个学校的最多录取人数
接下来的N行,每一行输入2+K个数,分别代表学生的GE(高考成绩)、GI(面试成绩)、K个志愿
录取规则:
(1)根据学生的GE和GI平均成绩从高到低排名,相等则继续比较GE,GE如果也相等则两个学生排名相同;
(2)根据排名名单,依次看学生的志愿学校;
(3)如果当前志愿学校录取人数未满则录取该生;
(4)如果两学生排名一样,且申请的是同一所学校,那么学校即使录取名额超限,也必须录取他们。
于是:可能有学生所有志愿均被刷,也可能有学校录取不到学生。
思路很简单,用两个结构体存取school和student的信息,并按照录取规则进行依次录取。
#include<stdio.h> #include<stdlib.h> typedef struct{ int total; // 需要录取的人数 int already; // 当前已录取的人数 int select[100]; // 录取的学生 }School; // 学校信息 typedef struct{ float GE,GI,final; int id; int choice[6]; // 志愿 }Student; // 学生信息 int cmp(const void *a,const void *b) // student根据成绩排序 { Student * x = (Student*)a; Student * y = (Student*)b; if(x->final != y->final) return y->final*10 - x->final*10; else return y->GE*10 -x->GE*10; } int cmp2(const void *a,const void *b) // school录取学生编号升序排序 { int *x = (int *)a; int *y = (int *)b; return *x-*y; } int main() { int N,M,K; scanf("%d %d %d",&N,&M,&K); School school[M]; Student student[N],temp[N]; int i,j; for(i = 0;i<M;i++) { scanf("%d",&school[i].total); school[i].already = 0; for(j = 0;j<100;j++) school[i].select[j] = 99999; } for(i = 0;i<N;i++) { scanf("%f %f",&student[i].GE,&student[i].GI); student[i].final = (student[i].GE + student[i].GI)/2; student[i].id = i; for(j = 0;j<K;j++) scanf("%d",&student[i].choice[j]); for(;j<6;j++) student[i].choice[j] = -1; } // 在排序前将原始student信息保存在temp,用于扩招时使用(因为排序后的student下标和id不一致) for(i = 0;i<N;i++) { temp[i].final = student[i].final; temp[i].GE = student[i].GE; } qsort(student,N,sizeof(Student),cmp); // 学生按成绩排序 //依次遍历每个学生的每个志愿 for(i = 0;i<N;i++) { for(j = 0;j<K;j++) { int want = student[i].choice[j]; // want为当前学生当前志愿的学校编号 if(school[want].already<school[want].total) // 如果该校还未录取完毕 { school[want].select[school[want].already] = student[i].id; school[want].already++; break; } else // 考虑是否扩招 { //already-1下标的必是该校最后一个录进来的学生,与他比较即可。 if(temp[school[want].select[school[want].already-1]].final == student[i].final && temp[school[want].select[school[want].already-1]].GE == student[i].GE) // 如果GE和GI均相同则扩招 { school[want].select[school[want].already] = student[i].id; school[want].already ++; break; } } } } for(i = 0;i<M;i++) // 对每个学校的录取人序号升序排列 qsort(school[i].select,school[i].already,sizeof(int),cmp2); for(i = 0;i<M;i++) // 输出学校录取情况 { if(!school[i].already) // 没录取到学生 printf("\n"); else { for(j = 0;j<school[i].already;j++) { if(j == school[i].already-1) printf("%d\n",school[i].select[j]); else printf("%d ",school[i].select[j]); } } } return 0; }