PAT 1080 Graduate Admission C++版

本篇博客详细解析了PAT1080题目,通过C++代码模拟研究生招生流程,包括根据考生成绩排名、志愿及学院配额进行录取。文章提供了完整的代码实现,并附带测试用例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PAT 1080 Graduate Admission C++

1.题意

模拟研究生院招生录取过程。
浙大每年都有很多人报考(废话,不是这样的话,我也就不会落榜了 ̄へ ̄)。现在的问题是:对于许多考生,以及志愿信息,还有研究生院,该如何招生呢?本题给出的录取过程如下:

  • step 1:根据考生的两个分数(Ge,Gi)的平均分排名,如果排名相同,则比较Ge的分数,如果还相同,则排名相同。
  • step 2:得到考生的排名信息之后,针对其每个人的志愿进行录取。如果达到了每个院的录取限额之后便不再录取。
  • step 3:如果一个学院录取了一个排名相同的人之后,会超标,则就超标,不用担心。【这句话很关键,参见下面的英文表述】

If there is a tied rank, and if the corresponding applicants are applying to the same school, then that school must admit all the applicants with the same rank, even if its quota will be exceeded.

2.分析

其实这种模拟题还是很简单的。主要思想如下:

  • step 1:先按照要求排序
  • step 2:将排好序的学生逐个录取,看是否能够录取。这里需要注意排名相同,但是限额超标的情况(只要加个else条件即可)
  • step 3:将得到的结果放到set中,然后排序输出即可。
3.代码
#include<cstdio>
#include<iostream>
#include<vector>
#include<set>
#include<algorithm>
#define maxn 40005

using namespace std;

struct Student{
	double Ge,Gi;//标记两种成绩	  
	double avg;//平均成绩  用int存储貌似不合适
	int flag;//是否招收成功 1=成功 
	vector<int> choice;//表示每个申请者的志愿 
	int id;//初始id 
};


int cmp(Student s1,Student s2){
	if(s1.avg == s2.avg){
		return s1.Ge > s2.Ge;
	}
	return s1.avg > s2.avg;	 
}

int  N,M,K;
Student stu[maxn];

int main(){	
	cin >> N >> M >> K;
	int i,j,k;
	int quota[M];//每个学院的配额 
	vector<int> admi[M] ;//每个学院招收的学生的id 
	for(i = 0;i< M;i++){
		cin >> quota[i];
	}	
	int aca;//目标学院 
	for(i = 0;i< N;i++){
		cin >> stu[i].Ge >> stu[i].Gi ;
		stu[i].avg = (stu[i].Ge + stu[i].Gi) / 2;//取平均成绩 
		for(j = 0;j< K;j++){
			cin >> aca;
			stu[i].choice.push_back(aca); 
		}
		stu[i].id = i;//初始化id 
	}
	
	sort(stu,stu+N,cmp);
//	for(i = 0;i< N;i++){
//		cout << stu[i].avg << " ";
//	}
	//cout << "=====\n";

	//各个学院开始招收学生 
	for(i = 0;i< N;i++){//遍历每个学生 
		for(j = 0;j< K;j++){
			if(quota[stu[i].choice[j]] > 0){//如果每个学院还有剩余名额
			//	cout << "choice : "<< stu[i].choice[j] <<"\n";
				quota[stu[i].choice[j]] --;//名额减一
				admi[stu[i].choice[j]].push_back(i);//被该学院招收
				stu[i].flag = 1;//入学			 
				break;//跳出当前循环 
			}
			else{//如果名额已经没有了,但是最后录取的人和当前的人名次相同,则也要录取 				
				if(stu[admi[stu[i].choice[j]].back()].avg == stu[i].avg 
				&& stu[admi[stu[i].choice[j]].back()].Ge == stu[i].Ge)//vector最后一个元素 
				{
					//cout << "该学院当前的最后一名是:" << admi[stu[i].choice[j]].back() <<"\n";
					admi[stu[i].choice[j]].push_back(i);//被该学院招收
					stu[i].flag = 1;//入学			 
					break;//跳出当前循环 
				}
			} 
		}
	}

	set<int> res;
	// 输出每个学院招收的学生	
	for(i = 0;i < M;i++){
		for(j = 0;j< admi[i].size();j++){
			res.insert(stu[admi[i][j]].id);
			//cout << stu[admi[i][j]].id << " ";				
		}
		set<int> :: iterator temp ;
		for(set<int> ::iterator it = res.begin();it!=res.end();it++){
			temp = it;
			if(++temp != res.end()) cout << *it << " ";
			else cout << *it ;
		}
		res.clear();//清空 
		cout <<"\n";
	}	
} 
4.测试用例
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
5.执行结果

在这里插入图片描述

6.其它

这里用到了几个知识:

  • 使用double 存储成绩
  • 使用vector.back()取vector最后的一个元素
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liu16659

看书人不妨赏个酒钱?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值