PAT-AL 1039. Course List for Student

1、知识点:排序
2、思路:定义course结构、student结构:
struct course{
int ind, stu_num; //课程编号,选课学生数
char name_arr[MAXNI][STRLEN]; //学生姓名
};

struct student{
int order; //查询顺序
char name[STRLEN]; //姓名
vector course_ind; //课程编号
};
读入课程数组cour,然后按ind排序;读入查询学生数组stu_arr,按姓名排序。然后遍历课程,对于每门课的每个选课学生,按照二分查找查询学生表stu_arr中的姓名,如果找到,就将对应的课程编号加入该学生。最后将查询学生表stu_arr做数据离散化,映射到disc数组,遍历disc数组打印输出答案。

注意:
①尽量用C的内容而不是C++(代码换成C++版超时,而C版顺利AC,~~);
②学生姓名排好序按照二分查找提升效率,否则会超时;
③student结构中用了vector,如果用malloc分配内存会出错,直接定义stu_arr数组或者用new分配内存则没事。

/*用途:
**说明:
**算法:
*/

//#define LOCAL
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
#define MAXN 40000+10
#define MAXK 2500+10
#define MAXNI 200+10
#define STRLEN 10
struct student{
    int order;
    char name[STRLEN];
    vector<int> course_ind;
};

struct course{
    int ind, stu_num;
    char name_arr[MAXNI][STRLEN];
};
int N, K;
course *cour;
//student stu_arr[MAXN];
student *stu_arr;
int *disc;    //stu_arr的离散化数组

void init_course();
int cmp_course_ind(const void* a, const void* b);
void init_stu();
int cmp_order(const void* a, const void* b);
int find_name(char* name);    //二分查找姓名
void print_course_ind(int ind);
int main()
{
#ifdef LOCAL
    freopen(".in", "r", stdin);
    freopen(".out", "w", stdout);
#endif

    scanf("%d%d", &N, &K);
    cour = (course*)malloc(sizeof(course)*K);
    init_course();
    for(int i=0; i<K; i++){
        int ind, stu_num;
        char name[STRLEN];
        scanf("%d%d", &ind, &stu_num);
        for(int j=0; j<stu_num; j++){
            scanf("%s", name);
            cour[i].ind = ind;
            strcpy(cour[i].name_arr[cour[i].stu_num], name);
            cour[i].stu_num++;
        }
    }

    qsort(cour, K, sizeof(course), cmp_course_ind); 
//  stu_arr = (student*)malloc(sizeof(student)*N);  //出错 
    stu_arr = new student[N];
    for(int i=0; i<N; i++){
        scanf("%s", stu_arr[i].name);
        stu_arr[i].order = i;
    }

    qsort(stu_arr, N, sizeof(student), cmp_order);

    int index;
    char name[STRLEN];
    for(int i=0; i<K; i++){
        for(int j=0; j<cour[i].stu_num; j++){
            index = find_name(cour[i].name_arr[j]);
            if(index != -1)
                stu_arr[index].course_ind.push_back(cour[i].ind);
        }
    }

    disc = new int[N];
    for(int i=0; i<N; i++)
        disc[stu_arr[i].order] = i;

    for(int i=0; i<N; i++){
        int ind = disc[i];
        printf("%s %d", stu_arr[ind].name, stu_arr[ind].course_ind.size());
        print_course_ind(ind);
    }

    return 0;
}

void init_course()
{
    for(int i=0; i<K; i++)
        cour[i].ind = cour[i].stu_num = 0;
}

void print_course_ind(int ind)
{
    int len = stu_arr[ind].course_ind.size();
    for(int i=0; i<len; i++)
        printf(" %d", stu_arr[ind].course_ind[i]);
    printf("\n");
}

inline int cmp_course_ind(const void* a, const void* b)
{
    return (*(course*)a).ind - (*(course*)b).ind;
}

inline int cmp_order(const void* a, const void* b)
{
    return strcmp((*(student*)a).name, (*(student*)b).name) < 0 ? -1 : 1;   //注意这里的比较字符数组的方法
}

inline int find_name(char* name)
{
    int start, med, end;
    start = 0;
    end = N-1;
    med = (start + end) / 2;
    while(start <= end){
        if(strcmp(name, stu_arr[med].name) > 0)
            start = med+1;
        else if(!strcmp(name, stu_arr[med].name))
            return med;
        else
            end = med-1;

        med = (start + end) / 2;
    }
    return -1;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值