pat 甲级 1080(模拟题)

题目链接:https://pintia.cn/problem-sets/994805342720868352/problems/994805387268571136

思路:

1、题目大意是,模拟高考录取学生的过程,每个学生有三种成绩

(1)GE录取成绩(2)GI面试成绩(3)最终成绩GF=(GE+GI)/2;

按学生的排名有以下规则:

(1)学生的最终成绩从大到小排列

(2)学生的最终成绩相同的情况下,需要比较学生的面试成绩,从高到低,如果学生的面试成绩也相同,

那么他们拥有相同的排名。

录取规则:

(1)每个考生拥有k个志愿,优先考虑前面的志愿。

(2)每个学校有mi个录取名额,如果学生排名相同且超过录取名额,依然录取。

 

输入:

第一行,n,m,k表示学生人数,学校数目,每个考生可以报考的学校的数目。

第二行,m个表示每个学校最多录取的学生人数

之后,n行每个学生的信息

学生的GE,GI,然后k个学生想要报考的学校。

 

输出

每行,每行表示每个学校可以录取的学生的编号。如果某个学校没人报,就输出空行

 

思路:

1、学生的排名从小到大

2、每次学校录取可以录取的学生,如果学校的录取名额满了,并且将要录取的学生的排名和学校最后一名的

排名相同,依旧录取。(这里不用提前将学生的排名记录,直接比较GE和GF相同就行了)

3、注意当比较最后一个学生是一定是排序后的编号,但vc中存储的是原编号,所以要提前用mp记录一下。

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
using namespace std;
const int maxn = 40040;
struct Node{
	int GI,GE,GF,id,rk;
	int cho[10];
}; 
Node nd[maxn];
map <int,int> mp;
vector <int> vc[120];
int sch[120],m,n,k,vis[maxn];
bool cmp(Node a,Node b)
{
	if(a.GF!=b.GF) return a.GF>b.GF;
	else return a.GE>b.GE;
}

int main(void)
{
	int i,j,p;
	scanf("%d%d%d",&n,&m,&k);
	memset(vis,0,sizeof(vis));
	for(i=0;i<m;i++) scanf("%d",&sch[i]);
	for(i=0;i<n;i++)
	{
		scanf("%d%d",&nd[i].GE,&nd[i].GI);
		nd[i].id=i;
		nd[i].GF=(nd[i].GE+nd[i].GI)/2;
		for(j=0;j<k;j++) scanf("%d",&nd[i].cho[j]);
	}
	sort(nd,nd+n,cmp);
	for(i=0;i<n;i++)
	mp[nd[i].id]=i; //记录排序后的编号 
	for(i=0;i<n;i++)
	{
		for(j=0;j<k;j++)
		{
				if(sch[nd[i].cho[j]]>0)
				{
					vc[nd[i].cho[j]].push_back(nd[i].id);
					sch[nd[i].cho[j]]--;
					break;
				}
				else if(sch[nd[i].cho[j]]==0)
				{
					p=vc[nd[i].cho[j]].size();
					int tp=mp[vc[nd[i].cho[j]][p-1]]; //是排序后的编号 
					if(nd[tp].GF==nd[i].GF&&nd[tp].GE==nd[i].GE)
					{
						vc[nd[i].cho[j]].push_back(nd[i].id);break; //这里断开 
					}
				}
		}
	}
	for(i=0;i<m;i++)
	{
		if(vc[i].size()==0)
		{
			printf("\n");
			continue;
		}
		sort(vc[i].begin(),vc[i].end());
		for(j=0;j<vc[i].size()-1;j++)
		printf("%d ",vc[i][j]);
		printf("%d\n",vc[i][j]);
	}
	return 0;
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值