要求模拟学校志愿录取的情况。每个学生拥有两个成绩:笔试成绩(GE)、面试成绩(GI)。综合成绩(GF)计算公式为$GF=\left(GE+GI\right)/2$。要求按以下规则进行录取:
- 学生排名计算方法为:先按 GF 从高到低排序,如果 GF 相同,按 GE 从高到低排序。如果 GF 和 GE 都相同,则排名必须相同。
- 学校录取时,按排名从高到低依次录取。
- 采用平行志愿录取方式。每个学生可以申请 K 所学校,录取时按照申请学校的顺序依次进行录取。如果录取时学生申请的学校名额未满,则将该学生录取到这所学校,否则依次考虑他的其它志愿学校。如果一个学生未被任何志愿学校录取,那么这个学生将不幸落榜。
- 如果排名并列,并且相应的申请者正在同一所学校申请,那么即使超过学校录取名额,该学校也必须录取所有具有相同排名的申请者。
输入第一行包含 3 个正整数:N、M、K,分别表示申请的总人数、学校总数以及每份申请所含的志愿数。之后一行给出 M 个正整数,分别表示每所学校的名额数量。然后紧接着 N 行,每行按“GE GI 志愿”的格式输入一份申请的信息。学校由 0M-1 编号,申请按 0N-1 编号。
输出所有学校的录取结果。每所学校的录取结果必须占一行,其中包含学校录取的申请人编号。编号必须按升序排列,并用空格分隔。每行的末尾必须没有多余的空格。如果没有申请人被学校录取,则必须相应地输出空白行。
先定义一个类 Student,其中应该包括以下几种数据成员:id、GE、GI、GF 以及志愿 app。定义一个变量 quota 存储所有学校的名额数量。读取每个学生的申请时,更新相关信息。读取完毕后,按题目要求对所有申请进行排序,并计算所有学生的排名。然后按题意模拟录取过程即可。具体实现可见代码。
#include <bits/stdc++.h>
using namespace std;
using gg = long long;
struct Student {
gg id, ge, gi, gf; // gf表示最终成绩
array<gg, 6> app; //申请的学校
};
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
gg ni, mi, ki;
cin >> ni >> mi >> ki;
vector<gg> quota(mi);
for (gg& i : quota) { //读取每个学校的名额数量
cin >> i;
}
vector<Student> stu(ni);
for (gg i = 0; i < ni; ++i) { //读取每个学生的申请
cin >> stu[i].ge >> stu[i].gi;
for (gg j = 0; j < ki; ++j) {
cin >> stu[i].app[j];
}
stu[i].gf = stu[i].ge + stu[i].gi; //最终成绩不除2不会影响结果
stu[i].id = i;
}
sort(stu.begin(), stu.end(), [](const Student& s1, const Student& s2) {
return tie(s2.gf, s2.ge) < tie(s1.gf, s1.ge);
}); //排序
vector<gg> rank(ni); //记录学生排名
gg r = 1;
for (gg i = 0; i < stu.size(); ++i) { //计算排名
if (i == 0 or stu[i].gf != stu[i - 1].gf or
stu[i].ge != stu[i - 1].ge) {
r = i + 1;
}
rank[stu[i].id] = r;
}
vector<vector<gg>> ans(mi);
for (auto& s : stu) { //统计每个学生的志愿录取情况
for (gg i = 0; i < ki; ++i) {
gg j = s.app[i];
if (ans[j].size() < quota[j] or
(not ans.empty() and rank[s.id] == rank[ans[j].back()])) {
ans[j].push_back(s.id);
break;
}
}
}
for (auto& v : ans) { //输出
sort(v.begin(), v.end()); //学生编号要升序输出
for (gg i = 0; i < v.size(); ++i) {
cout << (i == 0 ? "" : " ") << v[i];
}
cout << "\n";
}
return 0;
}