题目 

题意:每个考生有两个成绩:GE和GI,最终成绩为(GE + GI) / 2;按照最终成绩排名,如果最终成绩相同,就按照GE排名,如果仍然相同,他们的排名就是相同的。每个申请者有K个选择院校,每个学校也有招生人数限制。按照排名先后,如果当前考生的第一个志愿学校的名额还没满,就录取进去;如果当前志愿名额满了但是该校最后一个录取的人的排名和当前考生相同,则不管招生人数限制,依旧应该被录取;否则考虑该生的下一个志愿。如果所有志愿都没有能被录取,则该生落榜。

tip:map+sort

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
struct ss {
	int num,Ge,Gi;
	double final_grade;
	vector<int> quato;
	int rank;
	bool admited=false;
};
bool cmp(struct ss a,struct ss b) {
	if(a.final_grade==b.final_grade)
		return a.Ge>b.Ge;
	return a.final_grade>b.final_grade;
}
int main() {
	int n,m,k;
	cin>>n>>m>>k;
	int school[m];
	for(int i=0; i<m; ++i)
		cin>>school[i];
	struct ss s[n];
	for(int i=0; i<n; ++i) {
		s[i].num=i;
		cin>>s[i].Ge>>s[i].Gi;//两种成绩
		s[i].final_grade=(s[i].Ge+s[i].Gi)/2.;//总分
		for(int j=0; j<k; ++j) {
			int t;
			cin>>t;
			s[i].quato.push_back(t);//志愿学校
		}
	}
	sort(s,s+n,cmp);
	s[0].rank=1;
	for(int i=1; i<n; ++i) {
		if(s[i].final_grade==s[i-1].final_grade&&s[i].Ge==s[i-1].Ge)
			s[i].rank=s[i-1].rank;
		else s[i].rank=i+1;
	}
	vector<vector<int>> admitted(m);//录取名单
	for(int i=0; i<n; ++i) {
		if(!s[i].admited) {//没被录取的人进入录取工作
			for(int j=0; j<s[i].quato.size(); ++j)
				if(school[s[i].quato[j]]>0) { //当前最期许的学校有名额
					admitted[s[i].quato[j]].push_back(s[i].num);
					school[s[i].quato[j]]--;
					s[i].admited=true;
					int t=s[i].quato[j];
					while(i<n-1&&s[i].rank==s[i+1].rank) {
						for(int l=0; l<s[i+1].quato.size(); ++l)
							if(school[s[i+1].quato[l]]>0&&t!=s[i+1].quato[l]) {
								break;//排名相同者,但是后者与前者可选择院校不一样时,跳过
							} else if(t==s[i+1].quato[l]) {//排名相同者,且可选择的院校相同者都得录取
								admitted[t].push_back(s[i+1].num);
								school[t]--;
								s[i+1].admited=true;
								break;
							}
						++i;
					}
					break;
				}
		}
	}
	for(int i=0; i<m; ++i) {
		sort(admitted[i].begin(),admitted[i].end());
		if(admitted[i].size())
			cout<<admitted[i][0];
		for(int j=1; j<admitted[i].size(); ++j)
			cout<<" "<<admitted[i][j];
		cout<<endl;
	}
	return 0;
}