题目链接:https://pintia.cn/problem-sets/994805342720868352/problems/994805387268571136
思路:
1、题目大意是,模拟高考录取学生的过程,每个学生有三种成绩
(1)GE录取成绩(2)GI面试成绩(3)最终成绩GF=(GE+GI)/2;
按学生的排名有以下规则:
(1)学生的最终成绩从大到小排列
(2)学生的最终成绩相同的情况下,需要比较学生的面试成绩,从高到低,如果学生的面试成绩也相同,
那么他们拥有相同的排名。
录取规则:
(1)每个考生拥有k个志愿,优先考虑前面的志愿。
(2)每个学校有mi个录取名额,如果学生排名相同且超过录取名额,依然录取。
扫描二维码关注公众号,回复:
4134695 查看本文章
输入:
第一行,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;
}