PAT----A1080 Graduate Admission (30point(s))

A1080 Graduate Admission (30point(s))

题意

给出学生的成绩,k个志愿,k个学校的录取名额,学生按照总体成绩和Ge排名,排名靠前的优先录取,如果那所学校已经满了但是录取的最后一位学生的排名和他相同,也可以录取。
最后输出各个学校录取的学生的id。(从0到n-1)
如果该学生没有被任何学校录取,那么非常遗憾,他就名落孙山了,这也是非常令人扼腕叹息的事情。唉。

思路

注意一旦录取成功后break。

总结

排序题。结构体School虽然显得有点多余,但是还是比较符合直觉的。
Sample Input:

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

Sample Output:

0 10
3
5 6 7
2 8

1 4
#include"bits/stdc++.h"
using namespace std;
struct Student {
	int g1,g2;
	double g;
	int rank;
	int id;
	vector<int> a;
};
struct School {
	int cnt;
	vector<Student*> stus;
};
int main() {
	//freopen("input.txt","r",stdin);
	int n,m,k;
	cin >> n >> m >> k;
	map<int,School> id2School;
	for(int i=0; i<m; i++) {
		int t;
		scanf("%d",&t);
		id2School[i].cnt = t;
	}
	vector<Student> stus(n);
	for(int i=0; i<n; i++) {
		stus[i].a.resize(k);
		stus[i].id = i;
		scanf("%d%d",&stus[i].g1,&stus[i].g2);
		stus[i].g = (stus[i].g1 + stus[i].g2)/2.0;
		for(int j=0; j<k; j++)  scanf("%d",&stus[i].a[j]);
	}
	sort(stus.begin(),stus.end(),[](Student& s1,Student& s2) {
		if(s1.g == s2.g)
			return s1.g1 > s2.g1;
		return s1.g > s2.g;
	});
	// give rank
	for(int i=0; i<n; i++) {
		if(i == 0) {
			stus[i].rank = i;
			continue;
		} else if(stus[i].g == stus[i-1].g && stus[i].g1 == stus[i-1].g1) {
			stus[i].rank = stus[i-1].rank;
		} else
			stus[i].rank = i;
	}
	// admission
	for(auto& stu:stus) {
		for(int t:stu.a) {
			School& school = id2School[t];
			if(school.cnt) {
				school.cnt --;
				school.stus.push_back(&stu);
				break;
			} else if(stu.rank == school.stus.back()->rank) {
				school.stus.push_back(&stu);
				break;
			}
		}
	}
	// output
	for(int i=0; i<m; i++) {
		School& school = id2School[i];
		sort(school.stus.begin(),school.stus.end(),[](Student* s1,Student* s2) {
			return s1->id < s2->id;
		});
		for(int j=0; j<school.stus.size(); j++) {
			printf("%d",school.stus[j]->id);
			if(j != school.stus.size()-1) printf(" ");
		}
		cout << endl;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值