PAT甲级刷题之路——A1080 Graduate Admission

PAT甲级1080 Graduate Admission

    • PAT A1080 Graduate Admission(30分)
      • 原题如下
      • 题意理解
      • 自己的想法
      • 答案反馈
        • 这次用的一些小技巧
        • 然后总结下我这次犯的错误:
      • 代码
      • 结语

PAT A1080 Graduate Admission(30分)

原题如下

PAT甲级刷题之路——A1080 Graduate Admission_第1张图片
PAT甲级刷题之路——A1080 Graduate Admission_第2张图片
PAT甲级刷题之路——A1080 Graduate Admission_第3张图片

题意理解

每一份申请包含两个成绩:国家通过考试成绩 G E G_E GE,面试成绩 G I G_I GI,最终成绩为 ( G E + G I ) / 2 (G_E+G_I)/2 (GE+GI)/2
然后通过以下规则录取:

  1. 根据申请的最终成绩排序,最后根据名次一个一个录取。
  2. 如果有相同的最终成绩,则根据国家通过考试成绩 G E G_E GE排序。如果仍然相同,则他们的排名一定相同。
  3. 每一个申请者有K次机会,是否接收根据她的机会:如果根据排名被录取,如果最喜欢的学校未被录取,则看次喜欢的学校直至k个学校均不接收。
  4. 即使学校的招生限制到了但是学校必须接收相同排名的学生。
    输入:
    N:申请者的数量。 M:学校的数量。 K:申请者的机会。
    M个学校的招生限制
    接下来K行
    G E G_E GE G I G_I GI 喜欢的K个学校的ID
    输出:
    分别输出这M所学校接收的学生ID并按增序输出。若该学校未接收人员则输出空行。

自己的想法

排序问题,但是棘手的是每个学生有K次机会。

  1. 首先每个人在它所有的大学里都排个序
  2. 然后这些大学把其中符合当前符合第一志愿全部录取标记放入其对应的set中并把它从其他志愿中erase掉,然后接着第二志愿…第K志愿
  3. 最后输出每个学校录取的学生ID
    (以上想法不成立)啊啊啊不会啊!!
    柳神思路传送门
    看完思路以后恍然大悟,感觉自己好蠢啊。
    思路如下:
    先对每个学生进行排序,分高的先选学校。
    今日份代码(未debug完)先放一放,明天再来debug
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int limit[105];
struct student {
	int id, ge, gi, rk;
	vector<int> school;
}Std[40005];
vector<student> rk[105];
vector<int> ad[105];
bool flag_school[105] = { false };
int population[105] = { 0 };
int pp[105];
bool cmp(student& a,student &b){
	if ((a.ge + a.gi) != (b.ge + b.gi)) {
		return (a.ge + a.gi) > (b.ge + b.gi);
	}
	else {
		return a.ge > b.ge;
	}
}
int main() {
	int n, m, k;
	cin >> n >> m >> k;
	fill(pp, pp + 105, -1);
	for (int i = 0; i < m; i++) {
		cin >> limit[i];
	}
	for (int i = 0; i < n; i++) {
		cin >> Std[i].ge >> Std[i].gi;
		Std[i].id = i;
		for (int j = 0; j < k; j++) {
			int tt;
			cin >> tt;
			Std[i].school.push_back(j);
			rk[tt].push_back(Std[i]);
			flag_school[tt] = true;
		}
	}
	//对学生进行排序
	sort(Std, Std+n, cmp);
	//排名
	int rkk = 0, index1 = -1, index2 = -1;
	for (int i = 0; i < n; i++) {
		if (index1 != (Std[i].ge + Std[i].gi) || index2 != Std[i].ge) {
			rkk=i; Std[i].rk = rkk; index1 = Std[i].ge + Std[i].gi;
			index2 = Std[i].ge;
		}
		else {
			Std[i].rk = rkk;
		}
	}
	for (int i = 0; i < n; i++) {
		//分高的学生先选学校
		for (int j = 0; j < k; j++) {
			if (population[Std[i].school[j]] <= limit[Std[i].school[j]]) {
				population[Std[i].school[j]]++;
				ad[Std[i].school[j]].push_back(Std[i].id);
				if (Std[i].rk > pp[Std[i].school[j]])pp[Std[i].school[j]] = Std[i].rk;
			}
			else {
				//再判断是否最后一名和自己排名一样,若一样加入该学校
				if (Std[i].rk == pp[Std[i].school[j]]) {
					population[Std[i].school[j]]++;
					ad[Std[i].school[j]].push_back(Std[i].id);
				}
			}
		}
	}
	for (int i = 0; i < m; i++) {
		sort(ad[i].begin(), ad[i].end());
		for (int j = 0; j < ad[i].size(); j++) {
			if (j != 0)cout << ' ';
			cout << ad[i][j];
		}
		cout << endl;
	}
	return 0;
}

嘿嘿,我回来了,今天开始的有点晚,上午去弄保研的事了

答案反馈

PAT甲级刷题之路——A1080 Graduate Admission_第4张图片

这次用的一些小技巧

为了更愉快的debug,我用了很久没用的#ifdef…#endif语句,我不喜欢用集成环境里的断点debug,更喜欢自己编写语句让想输出的输出。
例如以下语句:

#ifdef test
	freopen("input.txt", "r",stdin);
#endif

这样只要把输入放入input.txt文件里,就不用每次把输入复制粘贴然后输出了,这一技巧是我今年寒假看紫书的时候学习到的。
只要在代码开头再加上:

#define test

就可以愉快的使用了,然后在OJ复制代码时不要复制这一行就可以避免测试代码没有删干净的情况。

然后总结下我这次犯的错误:

  1. 忘了把已录取的学生做标记,导致有些学生被多所学校录取
  2. 学生填报的志愿错把志愿标号当作学校ID压进去了,如下:
for (int j = 0; j < k; j++) {
			int tt;
			cin >> tt;
			//原来错误的写成下面这条语句
			//Std[i].school.push_back(j);
			Std[i].school.push_back(tt);
			//tt表示学校标号,j表示志愿标号
			rk[tt].push_back(Std[i]);
			//flag_school[tt] = true;
		}

代码

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int limit[105];//每个学校限制的招生人数
struct student {
	int id, ge, gi, rk;
	vector<int> school;
}Std[40005];
vector<student> rk[105];//学生的排名
vector<int> ad[105];//每个学校接收学生的id
bool flag[40005] = { false };//学生是否被录取
int population[105] = { 0 };//每个学校的已录取人数
int pp[105];//存放某一学校当前录取最后一名的排名
bool cmp(student& a,student &b){
	if ((a.ge + a.gi) != (b.ge + b.gi)) {
		return (a.ge + a.gi) > (b.ge + b.gi);
	}
	else {
		return a.ge > b.ge;
	}
}
int main() {
#ifdef test
	freopen("input.txt", "r",stdin);
#endif
	int n, m, k;
	cin >> n >> m >> k;
	fill(pp, pp + 105, -1);
	for (int i = 0; i < m; i++) {
		cin >> limit[i];
	}
	for (int i = 0; i < n; i++) {
		cin >> Std[i].ge >> Std[i].gi;
		Std[i].id = i;
		for (int j = 0; j < k; j++) {
			int tt;
			cin >> tt;
			Std[i].school.push_back(tt);
			rk[tt].push_back(Std[i]);
			//flag_school[tt] = true;
		}
	}
	//对学生进行排序
	sort(Std, Std+n, cmp);
	//排名
	int rkk = 0, index1 = -1, index2 = -1;
	for (int i = 0; i < n; i++) {
		if (index1 != (Std[i].ge + Std[i].gi) || index2 != Std[i].ge) {
			rkk=i; Std[i].rk = rkk; index1 = Std[i].ge + Std[i].gi;
			index2 = Std[i].ge;
		}
		else {
			Std[i].rk = rkk;
		}
	}
	for (int i = 0; i < n; i++) {
		//分高的学生先选学校
		if (flag[Std[i].id] == false) {
#ifdef test 
			cout << Std[i].id << '*' << endl;
#endif
			for (int j = 0; j < k; j++) {
				if (flag[Std[i].id] == false) {
					if (population[Std[i].school[j]] < limit[Std[i].school[j]]) {
						population[Std[i].school[j]]++;
						ad[Std[i].school[j]].push_back(Std[i].id);
						if (Std[i].rk > pp[Std[i].school[j]])pp[Std[i].school[j]] = Std[i].rk;
						flag[Std[i].id] = true;
#ifdef test
						cout << "****" << endl;
						cout << Std[i].id << ' ' << Std[i].school[j] << endl;
						cout << "****" << endl;
#endif
					}
					else {
						//再判断是否最后一名和自己排名一样,若一样加入该学校
						if (Std[i].rk == pp[Std[i].school[j]]) {
							population[Std[i].school[j]]++;
							ad[Std[i].school[j]].push_back(Std[i].id);
							flag[Std[i].id] = true;
#ifdef test
							cout << "---*" << endl;
							cout << Std[i].id << ' ' << Std[i].school[j] << endl;
							cout << "---*" << endl;
#endif
						}
					}
				}
			}
		}
	}
	for (int i = 0; i < m; i++) {
		sort(ad[i].begin(), ad[i].end());
		for (int j = 0; j < ad[i].size(); j++) {
			if (j != 0)cout << ' ';
			cout << ad[i][j];
		}
		cout << endl;
	}
	return 0;
}

结语

一遍写博客一遍做题感觉自己的思路开阔了不少,同时方便复习的时候总结自己的错误,本来一个人闷着刷题都快自闭了,用博客分享感觉也快落了不少~哈哈

你可能感兴趣的:(PAT甲级刷题之路)