A1047 Student List for Course (25分)(给出学生参与课程,然后统计每门课程有哪些学生)

/*
题意:
输入:
1、第一行给出总的学生人数,然后是课程数
2、然后给出每一行学生的姓名以及他的选课号

输出:
1、输入课程号,参加课程的学生人数
以及学生姓名,单独一行

解题:
1、以二位诶数组char[N][5]存放输入的姓名,其中char[i]表示第i个姓名
2、在读入数据时,如果某学生(编号i)选择了课程j,那么将该学生编号存到course[j]中,(即course[j].push_back(i)
3、对每一门课,将course[i]中的学生按姓名字典序从小到大排序,然后输出所要结果

learn && wrong:
1、使用string,最后一组数据容易超时,在这种数据量大的时候,最后使用char数组
2、vector来存放每门课程的选课学生的编号,可以有效防止所有学生选了所有课程的极端情况导致得空间超限
3、技巧:如果对字符串排序,那么会导致大量字符串移动,耗时,不如用字符串喜爱宝来代替字符串本身进行排序,耗时少得多

4、思路非常重要:
(向量数组为:每门课程参与的学生i)
首先读入学生人数以及课程数
然后读入学生以及他的选课数(用name[i]存学生)
接下来遍历选课数,读入选课号,将i压入每一个选课向量(其实就是用i作中间变量,来连接名字和选课)
接下来遍历选课,并且用sort排序每一个选课中的,再套一个遍历,遍历选课中的名字
*/

#include 
#include 
#include 
#include 
#include 
using namespace std;

const int maxn = 40010; //最大学生人数
const int maxc = 2510;  //最大课程门数

char name[maxn][5]; //maxn个学生
vector course[maxc];   //course[i]存放所有学生编号

bool cmp(int a, int b) {
    return strcmp(name[a], name[b]) < 0; //按姓名字典序从小到大排序
}

int main()
{
    int n, k, c, courseID;
    cin>>n>>k;    //学生人数以及课程数
    for (int i = 0;i < n;++i) {
        cin >> name[i] >> c; //学生姓名以及选课数
        for (int j = 0;j < c;j++) { //!!!又是错下标
            cin>>courseID;  //选择的课程编号
            course[courseID].push_back(i);  //将学生i加入第courseID门课中!!!核心
        }
    }

    for (int i = 1;i <= k;++i) {
        printf("%d %d\n", i, course[i].size());  //第i门课的学生数
        sort(course[i].begin(), course[i].end(), cmp);    //对第i门课的学生排序
        for (int j = 0;j < course[i].size();j++) {
            printf("%s\n", name[course[i][j]]);  //输出学生姓名
        }
    }
    return 0;
}

你可能感兴趣的:(A1047 Student List for Course (25分)(给出学生参与课程,然后统计每门课程有哪些学生))