PAT A1047 Student List for Course (25 分) 排序

60 篇文章 0 订阅

题目大意:给出N名学生的选课信息,输出所有课程的选课人数,并按姓名首字母顺序输出名单。

先存储再按姓名排序即可,耗时比较大,有优化空间。

AC代码:

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdio>

using namespace std;

int main()
{
    int N, K;
    scanf("%d%d", &N, &K);
    vector<vector<string>> list(N+1);
    for (int i = 0; i < N; ++i)
    {
        char name[10];
        int courseNum;
        scanf("%s%d", name, &courseNum);
        for (int j = 0; j < courseNum; ++j)
        {
            int courseId;
            scanf("%d", &courseId);
            list[courseId].push_back(string(name));
        }
    }
    for (int i = 1; i <= K; ++i)
    {
        printf("%d %d\n", i, list[i].size());
        sort(list[i].begin(), list[i].end());
        for (int j = 0; j < list[i].size(); ++j)
        {
            printf("%s\n", list[i][j].c_str());
        }
    }
    return 0;
}


优化方向:

① 建立姓名字符串到整型的映射,仍然采用最简单的方法,即将ABC0看成四位36进制数。

② 建立整型到姓名字符串的映射,避免使用map查找,即依次取出36进制数的每一位即可。

#include <bits/stdc++.h>

using namespace std;

int getId(char* name)
{
    return (name[0] - 'A') * pow(36,3) + (name[1] - 'A') * pow(36,2) + (name[2] - 'A') * 36 + name[3] - '0';
}

void getName(int id, char* name)
{
    name[0] = id / (int)pow(36,3) + 'A';
    name[1] = id % (int)pow(36,3) / (int)pow(36,2) + 'A';
    name[2] = id % (int)pow(36,2) / 36 + 'A';
    name[3] = id % 36 + '0';
}


int main()
{
    int N, K;
    scanf("%d%d", &N, &K);
    vector<vector<int>> v(K+1);
    for (int i = 0; i < N; ++i)
    {
        char name[5];
        int C;
        scanf("%s%d", name, &C);
        int id = getId(name);
        for (int j = 0; j < C; ++j)
        {
            int courseId;
            scanf("%d", &courseId);
            v[courseId].push_back(id);
        }
    }
    for (int i = 1; i <= K; ++i)
    {
        printf("%d %zu\n", i, v[i].size());
        sort(v[i].begin(), v[i].end());
        for (int j = 0; j < v[i].size(); ++j)
        {
            char name[5] = {0};
            getName(v[i][j], name);
            printf("%s\n", name);
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值