【题解】【AcWing】1566. 研究生入学

73 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

1566. 研究生入学

原题传送:AcWing 1566. 研究生入学

据说, 20112011 年,浙江省约有 100100 所研究生院准备着手处理 40,00040,000 多份入学申请。

如果你可以编写一个程序来自动执行录取流程,那将会很有帮助。

每个申请人都必须提供两个成绩:全国入学考试成绩 GEG_E 和面试成绩 GIG_I ,申请人的最终成绩是 (GE+GI)/2(G_E+G_I)/2

录取规则如下:

  • 申请者将根据其最终成绩由高到低进行排名,并且将从排名列表的顶部开始逐一录取。
  • 如果申请者的最终成绩并列,则按照 GEG_E 成绩由高到低进行排名,如果成绩仍然并列,则并列者的排名必须相同。
  • 每个申请人可以填报 KK 个志愿,并且将根据他/她的志愿进行录取:如果按照排名列表,轮到某位学生被录取了,并且其第一志愿学校还未招满人,则他成功被该学校录取。如果名额已满,则按顺序考虑其他志愿,直至成功被录取为止。如果所有报名学校都无法录取该名学生,则该名学生录取失败。
  • 如果出现并列排名,并且并列申请人正在申请同一所学校,那么该学校不得只录取其中一部分申请人,即使超过招生限额,也必须全部录取。

输入格式

第一行包含三个整数, NN 表示总申请人数量, MM 表示学校数量, KK 表示可填报志愿数量。

第二行包含 MM 个整数,表示每所学校的计划招生人数。

接下来 NN 行,每行包含 2+K2+K 个整数,前两个整数表示一名申请人的 GEG_EGIG_I ,接下来 KK 个整数,表示该申请人的志愿学校编号。

所有学校编号 0M10 \sim M-1 ,所有申请人编号 0N10 \sim N-1

输出格式

输出所有研究生院的录取结果。

每所学校的录取结果占据一行,其中包含所有学校录取的申请人的编号。编号必须按升序排列,并用空格分隔。

每行的末尾必须没有多余的空格。

如果某学校没有录取任何学生,则必须相应地输出空白行。

数据范围

1N400001 \le N \le 40000 , 1M1001 \le M \le 100 , 1K51 \le K \le 5 , 0GE,GI1000 \le G_E,G_I \le 100 , 每所学校的计划招生人数不会超过 20002000

输入样例:

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

输出样例:

0 10
3
5 6 7
2 8

1 4

思路:

先根据提意列出排名,从第一志愿开始录取,若成绩并列,则记录录取的学校,然后一起加入vector更新学校招生容量。

题解:

#include<bits/stdc++.h>

using namespace std;

const int N = 40010, M = 110, K = 5;

int n, m, k;
int cnt[N], wish[N];
vector<int> v[M];

struct Student
{
	int id, score1, score2, sum;
	int wish[K];
	
	bool operator< (const Student &t) const
	{
		if(sum != t.sum)
			return sum > t.sum;
		return score1 > t.score1;
	}
	
	bool operator== (const Student &t) const
	{
		return score1 == t.score1 && score2 == t.score2; 
	}
}s[N];

int main()
{	
	scanf("%d%d%d", &n, &m, &k);
	
	for(int i = 0; i < m; i++)
		scanf("%d", &cnt[i]);
	
	for(int i = 0; i < n; i++)
	{
		s[i].id = i;
		scanf("%d%d", &s[i].score1, &s[i].score2);
		for(int j = 0; j < k; j++)
			scanf("%d", &s[i].wish[j]);
		s[i].sum = s[i].score1 + s[i].score2;
	}
	sort(s, s + n);
	
	memset(wish, -1, sizeof wish);
	for(int i = 0; i < n;)
	{
		int j = i + 1;
		while(j < n && s[i] == s[j])
			j++;
		for(int t = i; t < j; t++)
		{
			for(int u = 0; u < k; u++)
			{
				int w = s[t].wish[u];
				if(cnt[w] > v[w].size())
				{
					wish[t] = w;
					break;
				}
			}
		}
		for(int t = i; t < j; t++)
			if(wish[t] != -1)
				v[wish[t]].push_back(s[t].id);
				
		i = j;			
	}
	
	for(int i = 0; i < m; i++)
	{
		if(v[i].size())
		{
			sort(v[i].begin(), v[i].end());
			printf("%d", v[i][0]);
			for(int j = 1; j < v[i].size(); j++)
				printf(" %d", v[i][j]);
		}
		printf("\n");
	}

	return 0;
}