PAT 1080

本文深入解析了一种高校招生算法,详细介绍了如何通过排序和排名来决定学生的录取情况,包括成绩计算、排名处理、超额录取条件及输出排序。文章提供了一个完整的代码实现,展示了算法的具体应用。

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

题目

原题目地址
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

代码及思路

  1. 先按照每个申请的成绩排序,然后给予排名
  2. 要注意当总成绩和Ge相同时两者有着同样的名次,在这里的名次处理对后面的录取有着很大帮助
  3. 注意超额录取的条件是和该学校最后一个录取的同学的排名相同时可以进行超额录取
  4. 超额录取时候要注意判空问题,因为有可能这个学校的录取本身就是0
  5. 最后输出的时候,要求是按照从小到大的学号输出,但程序的逻辑顺序是按照从成绩高低读入的,所以输出前要进行一次排序
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn = 400010;
const int maxm = 110;
const int maxk = 5;
struct applicant {
	int id;
	int ge, gi;
	int preschool[maxk];
	int avgscore;
	int rank;
}app[maxn];

int school[maxm];
vector<int> finaloffer[maxm];
int m, n, k;

bool cmp(applicant a, applicant b) {
	if (a.avgscore != b.avgscore) return a.avgscore > b.avgscore;
	else if (a.ge != b.ge) return a.ge > b.ge;
	else return a.id < b.id;
}

int main() {
	scanf("%d %d %d", &n, &m, &k);
	for (int i = 0; i < m; i++) {
		scanf("%d", &school[i]);
	}
	for (int i = 0; i < n; i++) {
		scanf("%d %d", &app[i].ge, &app[i].gi);
		app[i].id = i;
		app[i].avgscore = (app[i].ge + app[i].gi) / 2;
		for (int j = 0; j < k; j++) {
			scanf("%d", &app[i].preschool[j]);
		}
	}
	sort(app, app + n, cmp);
	app[0].rank = 1;
	for (int i = 1; i < n; i++) {
		if (app[i].avgscore == app[i - 1].avgscore && app[i].ge == app[i - 1].ge) {
			app[i].rank = app[i - 1].rank;
		}
		else
			app[i].rank = i;
	}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < k; j++) {
			if (school[app[i].preschool[j]] > 0) {
				school[app[i].preschool[j]]--;
				finaloffer[app[i].preschool[j]].push_back(app[i].id);
				break;
			}
			else if (finaloffer[app[i].preschool[j]].size() != 0 && school[app[i].preschool[j]] == 0 && app[i].rank == app[finaloffer[app[i].preschool[j]][finaloffer[app[i].preschool[j]].size() - 1]].rank) {
				finaloffer[app[i].preschool[j]].push_back(app[i].id);
				break;
			}
		}
	}
	for (int i = 0; i < m; i++) {
		sort(finaloffer[i].begin(), finaloffer[i].end());
	}
	for (int i = 0; i < m; i++) {
		if (finaloffer[i].size() == 0) {
			printf("\n");
			continue;
		}
		else {
			for (int j = 0; j < finaloffer[i].size(); j++) {
				printf("%d", finaloffer[i][j]);
				if (j != finaloffer[i].size() - 1) printf(" ");
			}
			printf("\n");
		}
	}
	return 0;
}

有两个测试点 4分无法通过,等二刷解决吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值