解题过程的小记录,如有错误欢迎指出。
难度:三星(用map会超时,必须用vector配合hash散列,hash的大小设置和映射过程可以背一下)
题目分析
给出每一门课的选课学生,然后按照学生名字进行查询,输出每个学生所选的课程
(其实题目中说了名字是有一定规律的:三个大写字母+一个数字,就是在暗示用hash映射来做)
注意点
- 最后一个测试点数据量过大,所以用map的方法过不了
- 输出的课程序号需要按照从小到大排序
我的解题过程
思路
- 因为学生姓名是三个大写字母+一个数字的结构,所以可以开一个大小为26 * 26 * 26 * 10的vector数组用来映射学生(相当于是一个千位、百位、十位都是26进制,个位是十进制的数字=>这样就不会重复),因为学生会选择多门课程,所以hash表的类型选取vector
- 设置一个函数,返回把学生姓名映射到数组上的下标
- 按课程输入学生所选的课程
- 按照要求进行输出
bug
- 刚开始还是选用了map来写,本题用map来写真的十分方便,但是最后一个测试点会gg,会扣一分
- 后来改了vector配合散列hash,结果数组大小写错了映射方法也是,导致最后一个测试点报错,会扣两分(这还不如超时呢orz)
- 最后一切都对了,但是程序运行不了了,相同的代码可以提交全对,但是在VS2017中运行不了,后来查了一下是因为数组开太大了,不能放在main里,一定要放的话可以加static设置,变为全局变量,也可以直接放在外面变成全局变量
代码
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
vector<int> stu[26 * 26 * 26 * 10];//***编译器毛病:数组下标开大了放在全局变量就可以运行
int indexnum(string s) {
int result = 0;
for (int i = 0; i < 3; i++) {
result = result * 26 + (s[i] - 'A');
}
result = result * 10 + (s[3] - '0');
return result;
}
int main()
{
int n, k;
cin >> n >> k;
for (int i = 0; i < k; i++) {
int courseid, stunum;
scanf("%d %d", &courseid, &stunum);
for (int j = 0; j < stunum; j++) {
string s;
cin >> s;
stu[indexnum(s)].push_back(courseid);
}
}
for (int i = 0; i < n; i++) {
string s;
cin >> s;
int sizenum = stu[indexnum(s)].size();
cout << s << " " << sizenum;
if (sizenum != 0) {
sort(stu[indexnum(s)].begin(), stu[indexnum(s)].end());
for (int j = 0; j < sizenum; j++) {
printf(" %d", stu[indexnum(s)][j]);
}
}
printf("\n");
}
return 0;
}
dalao的代码
全部代码因版权原因不放出来,大家可以自行去柳神博客购买或者参考晴神的上机笔记~
借鉴点
- hash的大小设置,和下标映射方法最好了解并背下来