PAT A1080 Graduate Admission

这篇博客详细介绍了PAT A1080 Graduate Admission的模拟录取过程,包括录取规则、排序标准和处理并列问题的方法。博主提出了双指针法的解决方案,通过排序考生并使用[left, right)区间处理同排名考生,确保能同时进入同一学校。此外,还提及了使用邻接链表来存储同排名学生,并通过遍历和管理学校名额来实现录取。提供了不同阶段的代码思路,从T2到T4,逐步完善解决方案。" 131705967,8515779,Spring Boot与ElasticsearchRepository深度整合,"['spring boot', '后端', 'elasticsearch', '数据仓库', '数据操作']

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

PAT A1080 Graduate Admission

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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
wordmeaning
automatevt. 使自动化
admittedv. 承认
quotan. 配额
  • 题意:
    模拟学校录取,每个学校名额存在quota[ ]里
    每个考生有两个成绩:初试GE,复试GI,及志愿表pSchool[ ]
    排序规则:先按平均分(==总分),再按GE,都同并列(★并列问题)
    排好序后,从第一名开始选学校,每个人都是从第一志愿开始,一直向后匹配:直到匹配到1)学校有名额2)和人并列进同一学校,或者匹配到最后一个志愿也没匹配成功 -> 没学上了
    输出每个学校招的学生(递增),结尾不多空格,没有招到输出空行

  • 思路 1:双指针法
    将所有考生排序后,用[left , right)框住同一"排名"的人,这样从头到尾一组一组处理(以解决:并列进同一个学校的问题),若一个人有学上,就把他加入到对应学校的vector中去,最后循环将每个学校的vector排序输出

  • code 1:

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <vector>
using namespace std;
int n, m, k;
int quota[110];
vector<int> admit[110];	//存储各学校招生情况 
struct Stu{
	int id, gE, gI, fG, pSchool[6];
}stu[400100];
bool cmp(Stu& a, Stu& b){
//TIPS 1: 这里要使用&引用传参,不然会超时! 
	if(a.fG != b.fG) return a.fG > b.fG;
	else return a.gE > b.gE;
}
int main(){
	scanf("%d %d %d", &n, &m, &k);
	for(int i = 0; i < m; ++i){
		scanf("%d", &quota[i]);
	}
	for(int i = 0; i < n; ++i){
		scanf("%d %d", &stu[i].gE, &stu[i].gI);
		stu[i].id = i;
		stu[i].fG = stu[i].gE + stu[i].gI;
		for(int j = 0; j < k; ++j){
			scanf("%d", &stu[i].pSchool[j]);
		}
	}
	sort(stu, stu+n, cmp);
	int left = 0, right = 0;
	while(right < n){
		while(stu[right].fG == stu[left].fG && stu[right].gE == stu[left].gE && right < n){
		//Wrong 1: 这个循环条件导致了最后一个测试点 段错误: 
		//如果right不加限制,后面都是0可能会一直累加下去,导致while执行判断条件时数组越界 
			right++;
		} 
		int preS = -1; 	//上一个人去的学校  TIPS 2:每轮循环开始置为-1,防止边界出问题 	
		for(int i = left; i < right; ++i){
			for(int j = 0; j < k; ++j){
				if(quota[stu[i].pSchool[j]] > 0){
				//如果学校还有名额
					quota[stu[i].pSchool[j]]--;
					admit[stu[i].pSchool[j]].push_back(stu[i].id);
					preS = stu[i].pSchool[j];
					break;
				}else if(stu[i].pSchool[j] == preS){
				//或者没名额但是是上一个同排名消耗掉的 
					quota[stu[i].pSchool[j]]--;
					admit[stu[i].pSchool[j]].push_back(stu[i].id);
					preS = stu[i].pSchool[j];
					break;
				} 
			}
		}
		left = right;
	}
	for(int i = 0; i < m; ++i){
		sort(admit[i].begin(), admit[i].end());
		for(int j = 0; j < admit[i].size(); ++j){
			if(j != 0) printf(" ");
			printf("%d", admit[i][j]);
		}
		printf("\n");
	}
	return 0;
} 

  • 思路:vector<Stu> rank[maxn]
    用一个邻接链表 存储同一排名的学生
    从头开始遍历每组(同排名为一组)学生,并用一个mp记录该组学生上的学校,两种情况可以被录取:1)志愿学校有名额 2)志愿学校没名额,但是同组人整没得

  • T2 code:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 50010;
int quota[110];
struct Stu{
	int id, ge, gi, gf, K[6];
}stu[maxn];
vector<Stu> r[maxn];
vector<int> admit[110];
bool cmp(Stu a, Stu b){
	return a.gf != b.gf ? a.gf > b.gf : a.ge > b.ge;
}
int main(){
	int n, m, k;	//n == Stu, m == Sch, k == Choices;
	scanf("%d %d %d", &n, &m, &k);
	for(int i = 0; i < m; ++i){
		scanf("%d", &quota[i]);
	}
	for(int i = 0; i < n; ++i){
		scanf("%d %d", &stu[i].ge, &stu[i].gi);
		stu[i].id = i;
		stu[i].gf = stu[i].ge + stu[i].gi;
		for(int j = 0; j < k; ++j){
			scanf("%d", &stu[i].K[j]);
		}
	}
	sort(stu, stu+n, cmp);
	r[0].push_back(stu[0]);
	int idex = 0;
	for(int i = 1; i < n; ++i){
		if(stu[i].gf == stu[i-1].gf && stu[i].ge == stu[i-1].ge) r[idex].push_back(stu[i]);
		else{
			r[++idex].push_back(stu[i]);
		} 		
	}
	for(int i = 0; i <= idex; ++i){
		unordered_map<int, bool> mp;
		for(int j = 0; j < r[i].size(); ++j){
			int now = r[i][j].id;
			for(int h = 0; h < k; ++h){
				int perfer = r[i][j].K[h];
				if(quota[perfer] > 0 || mp[perfer]){	//Wrong 1: if(x > 0) >0要写出来 
					admit[perfer].push_back(now);
					quota[perfer]--;
					mp[perfer] = true;
					break;
				} 
			}
		}	
	}
	
	for(int i = 0; i < m; ++i){
		sort(admit[i].begin(), admit[i].end()); 
		for(int j = 0; j < admit[i].size(); ++j){
			if(j == 0) printf("%d", admit[i][j]);
			else printf(" %d", admit[i][j]);
		}
		printf("\n");
	}
	return 0;
} 
  • T3 code:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 300;
int quota[maxn];
struct Stu
{
    int id, ge, gi, fg, choice[6];
}stu[40010];
vector<int> sch[maxn];
bool cmp(Stu a, Stu b)
{
    return a.fg != b.fg ? a.fg > b.fg : a.ge > b.ge;
}
int main()
{
    int n, m, k;
    scanf("%d %d %d", &n, &m, &k);
    for(int i = 0; i < m; ++i)
    {
        scanf("%d", &quota[i]);
    }
    for(int i = 0; i < n; ++i)
    {
        scanf("%d %d", &stu[i].ge, &stu[i].gi);
        for(int j = 0; j < k; ++j)
        {
            scanf("%d", &stu[i].choice[j]);
        }    
        stu[i].fg = stu[i].ge + stu[i].gi;

        stu[i].id = i;
        
    }        
    sort(stu, stu+n, cmp);
    int left = 0, right = 1;
    while(left < n)
    {   //WRONG 样例5 注意双指针:内部循环也要 < n
        while(right < n && stu[right].fg == stu[left].fg && stu[right].ge == stu[left].ge) right++;
        vector<bool> mp(m, false);
        for(int i = left; i < right; ++i)
        {
            for(int j = 0; j < k; ++j)
            {
                int tc = stu[i].choice[j];
                if(mp[tc] == false && quota[tc] <= 0) continue;
                quota[tc]--;
                mp[tc] = true;
                sch[tc].push_back(stu[i].id);
                break;
            }
        }
        left = right++;
    }
    for(int i = 0; i < m; ++i)
    {
        sort(sch[i].begin(), sch[i].end());
        for(int j = 0; j < sch[i].size(); ++j)
        {
            if(j == 0) printf("%d", sch[i][j]);
            else printf(" %d", sch[i][j]);
        }
        printf("\n");
    }
    return 0;
}

  • T4 code:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 40010;
int quota[110], perfer[maxn][6], score[maxn][3];
bool first[110];
vector<int> candidate, ans[110];

bool cmp(int a, int b)
{
    return score[a][2] != score[b][2] ? score[a][2] > score[b][2] : score[a][0] > score[b][0];
}
int main()
{
    int n, m, k;
    scanf("%d %d %d", &n, &m, &k);
    for(int i = 0; i < m; ++i)
    {
        scanf("%d", &quota[i]);
    }
    for(int i = 0; i < n; ++i)
    {
        scanf("%d %d", &score[i][0], &score[i][1]);
        score[i][2] = score[i][0] + score[i][1];
        candidate.push_back(i);
        for(int j = 0; j < k; ++j)
        {
            scanf("%d", &perfer[i][j]);
        }
    }
    sort(candidate.begin(), candidate.end(), cmp);
    for(int i = 0; i < candidate.size(); ++i)
    {
        int tmp = candidate[i];
        if(i != 0 && (score[tmp][2] != score[candidate[i-1]][2] || score[tmp][0] != score[candidate[i-1]][0]))
        {
            memset(first, false, sizeof(first));
        }
        for(int j = 0; j < k; ++j)
        {
            int aim = perfer[tmp][j];
            if(first[aim] == false && quota[aim] <= 0)
            {
                continue;
            }
            quota[aim]--;
            ans[aim].push_back(tmp);
            first[aim] = true;
            break;
        }
//printf("%d ge=%d gi=%d gf=%d\n", candidate[i], score[candidate[i]][0], score[candidate[i]][1], score[candidate[i]][2]);
    }
    for(int i = 0; i < m; ++i)
    {
        sort(ans[i].begin(), ans[i].end());
        for(int j = 0; j < ans[i].size(); ++j)
        {
            printf("%d", ans[i][j]);
            if(j < ans[i].size() - 1) printf(" ");
        }
        printf("\n");
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值