4.1排序 A1080 Graduate Admission (30 分)

// 02.22 13:35-17:00
#include <algorithm>
#include <cstdio>
using namespace std;

struct Student {
    int GE, GI, sum, r, id;
    int cho[6];
} stu[40010];

struct School {
    int quota;
    int stuNum;     //当前录取人数
    int id[40010];  //存储录取了哪些考生
    int lastAdmit;  //存储上一个录取的考生id,方便破格录取
} sch[110];

bool cmpStu(Student a, Student b) {
    if (a.sum != b.sum)
        return a.sum > b.sum;
    else
        return a.GE > b.GE;
}

bool cmpID(int a, int b) {
    return stu[a].id < stu[b].id;
}

int main() {
    int n, m, k;  // n考生人数,m学校个数,k志愿个数
    scanf("%d%d%d", &n, &m, &k);
    //录入学校信息
    for (int i = 0; i < m; i++) {
        scanf("%d", &sch[i].quota);  // 学校的招生名额
        sch[i].stuNum = 0;           //当前已招生人数
        sch[i].lastAdmit = -1;       // -1表示上一个不存在
    }
    // 录入学生信息
    for (int i = 0; i < n; i++) {
        stu[i].id = i;  //考生id
        scanf("%d%d", &stu[i].GE, &stu[i].GI);
        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);
    //对学生计算排名,从0开始
    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];  //当前学生的当前学校id
            int num = sch[choice].stuNum;  //当前学生的当前学校的已录取人数
            int last = sch[choice].lastAdmit;  //当前学校的上一个录取人数
            // 怎么才能录取呢?
            // 条件:当前学生选择的志愿的学校名额没满,或,当前学校录取的上一个学生的排名和当前学生的排名相同
            if (num < sch[choice].quota ||
                (last != -1 && stu[i].r == stu[last].r)) {
                sch[choice].id[num] = i;  //录取啦,(^-^)V,将当前考生id插入到该学校的所有编号中
                sch[choice].stuNum++;       //当前学校的已录取人数++
                sch[choice].lastAdmit = i;  //当前学校的上一个录取id变了
                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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值