算法竞赛入门经典(紫书)第四章——A Typical Homework UVA-12412

14 篇文章 0 订阅

题意:
这道题目很像上课布置的大作业,但是放到这里就需要我们去纠结格式之类的细节问题了。
题目中总共有 5 个操作:Add,Remove,Query,Show ranking,Show Statistics,看过一遍题目后就会发现 Show ranking 不需要怎么考虑,所以我们要操心的就是剩下四种操作。

主菜单是下面代码运行的结果(为了消除大家对换行等格式问题的疑虑,就用代码来表示了,下文一样)

printf("Welcome to Student Performance Management System (SPMS).\n\n");
printf("1 - Add\n");
printf("2 - Remove\n");
printf("3 - Query\n");
printf("4 - Show ranking\n");
printf("5 - Show Statistics\n");
printf("0 - Exit\n\n");

1
主菜单下输入 1,进入 Add 功能。
然后会运行下面的输出:

printf("Please enter the SID, CID, name and four scores. Enter 0 to finish.\n");

这里要求新学生的 SID 不能和已有学生的 SID 相同,如果相同则会有下面的输出:

printf("Duplicated SID.\n");

然后这个新学生的数据被忽略,即不被加入。
但是新学生的 name 可以和已有学生的相同。

参照输入输出样例,每次输入一次数据后还会输出”Please enter the SID, CID, name and four scores. Enter 0 to finish.\n”一遍,可见这条语句的输出在循环里面,循环以输入的是 0 为结束。

2
主菜单下输入 2,进入 Remove 功能。
然后会运行下面的输出:

printf("Please enter SID or name. Enter 0 to finish.\n");

这里输入的数据可能是 SID 也可能是 name,所以比较时既要考虑和学生数据的 SID 比较,又要和 学生数据的 name 比较。
然后执行删除操作,删除完后要输出删除了几个学生。

printf("%d student(s) removed.\n", num);  //num为统计的删除学生的数量

参照输入输出样例,每次输入一次数据后还会输出”Please enter SID or name. Enter 0 to finish.\n”一遍,可见这条语句的输出在循环里面,循环以输入的是 0 为结束。

3
主菜单下输入 3,进入 Query 功能。
然后会运行下面的输出:

printf("Please enter SID or name. Enter 0 to finish.\n");

这里输入的数据可能是 SID 也可能是 name,所以比较时既要考虑和学生数据的 SID 比较,又要和 学生数据的 name 比较。
然后执行查找操作,如果找不到就什么也不输出。
如果找到了,就按 “%d %s %d %s %d %d %d %d %d %.2lf”, rank, SID, CID, name, Chinese, Mathematics, English, Programming, total, average” 的格式输出。
如果找到了多个,按 Add 的先后输出这些学生,先 Add 进的先输出。

这里的 rank 的规则是,如果分数一样则算同一个排名,比如 Tom 100,John 100,Alice 90,则 Tom 和 John 是第 1 名,Alice 是第二名。

参照输入输出样例,每次输入一次数据后还会输出”Please enter SID or name. Enter 0 to finish.\n”一遍,可见这条语句的输出在循环里面,循环以输入的是 0 为结束。

4
主菜单下输入 4,进入 Show ranking 功能。
然后会运行下面的输出:

printf("Showing the ranklist hurts students' self-esteem. Don't do that.\n");

然后就回到主菜单了,就酱。

5
主菜单下输入 5,进入 Show Statistics 功能。
然后会运行下面的输出:

printf("Please enter class ID, 0 for the whole statistics.\n");

输入的数据是班级的 ID,如果输入的是 0 则输出的是所有班级的数据。
然后会有下面的统计数据输出

printf("Chinese\n");
printf("Average Score: %.2lf\n", 该班级语文的平均成绩);
printf("Number of passed students: %d\n", 该班级语文的及格人数);
printf("Number of failed students: %d\n\n", 该班级语文的不及格人数);

printf("Mathematics\n");
printf("Average Score: %.2lf\n", 该班级数学的平均成绩);
printf("Number of passed students: %d\n", 该班级数学的及格人数);
printf("Number of failed students: %d\n\n", 该班级数学的不及格人数);

printf("English\n");
printf("Average Score: %.2lf\n", 该班级英语的平均成绩);
printf("Number of passed students: %d\n", 该班级英语的及格人数);
printf("Number of failed students: %d\n\n", 该班级英语的不及格人数);

printf("Programming\n");
printf("Average Score: %.2lf\n", 该班级编程的平均成绩);
printf("Number of passed students: %d\n", 该班级编程的及格人数);
printf("Number of failed students: %d\n\n", 该班级编程的不及格人数);

printf("Overall:\n");
printf("Number of students who passed all subjects: %d\n", 该班级 4 门课都及格的人数);
printf("Number of students who passed 3 or more subjects: %d\n", 该班级至少有 3 门课及格的人数);
printf("Number of students who passed 2 or more subjects: %d\n", 该班级至少有 2 门课及格的人数);
printf("Number of students who passed 1 or more subjects: %d\n", 该班级至少有 1 门课及格的人数);
printf("Number of students who failed all subjects: %d\n\n", 该班级 4 门课都不及格的人数);

输出完后回到主菜单

0
主菜单下输入 0,程序退出。

思路:
除了一些格式上的问题我们需要注意,关键的就是逻辑上的问题了。
从题目中我们能够看到我们需要计算每名学生的总成绩、平均成绩、排名,每个班级的每一科的平均成绩、及格人数、不及格人数及具体条件下的及格人数,所有班级的每一科的平均成绩、及格人数、不及格人数及具体条件下的及格人数。
另外需要注意的是每次 Add 或 Remove 操作都会影响学生的排名、班级的成绩等等数据,所以每次 Add 或 Remove 后都要对这些数据进行更新。

我的思路是,由于数据量比较小,学生最多不超过 100,所以将学生作为一个结构体,直接用大于 100 的数组来存学生的数据,每次 Add 或 Remove 后都对所有学生重新计算一遍排名和班级信息(由于数据量比较小,所以这样不会超时)。

Add 的思路是用一个变量指向学生数据的末尾,每次 Add 一个新的数据指针后移。

Remove 的思路是用一个 bool 类型的数组对每一个下标上的学生信息打标记,如果存在则为 true,如果不存在则为 false,Remove 后原来为 true 的标记变为 false 即可,这样就不用更改已存学生信息的位置了。

计算排名的思路是将学生信息所在的下标和总分提出来放到新的数组里,然后排序,排好序后按顺序对每一个学生信息填写排名。

计算班级信息的思路是用数组的 0 下标位置存所有班级的数据,其他的 i 下标位置存 i 班级的数据,遍历一遍所有学生的信息即可。

代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<stack>
#include<queue>
#include<utility>
#include<vector>
#include<cmath>
#include<set>
#include<map>
#include<iostream>
#include<algorithm>
#include<sstream>
using namespace std;
typedef long long LL;

struct Stu{  //学生
    char sid[15];
    int cid;
    char name[15];
    int scores[4];
    int tot;
    double ave;
    int rnk;

    Stu(){}

    Stu(char sd[15], int cd, char ne[15], int ss[4]){
        strcpy(sid, sd);
        cid = cd;
        strcpy(name, ne);
        tot = 0;
        for(int i=0; i<4; i++){
            scores[i] = ss[i];
            tot += ss[i];
        }
        ave = 1.0*tot/4+1e-5;
    }
};
typedef struct Stu Stu;

struct Rank{  //排名
    int id;
    int tot;
    Rank(){}
    Rank(int i, int t){
        id = i; tot = t;
    }
    bool operator < (const Rank& r){
        return tot > r.tot;
    }
};
typedef struct Rank Rank;

struct Class{  //班级
    int num;
    int scores[4];
    int passed[4];
    int failed[4];
    int overall[5];
    Class(){
        num = 0;
        for(int i=0; i<4; i++){
            scores[i] = 0;
            passed[i] = 0;
            failed[i] = 0;
        }
        for(int i=0; i<5; i++){
            overall[i] = 0;
        }
    }
};
typedef struct Class Class;

int n;
bool flag[110];
Stu stu[110];
Class cls[25];
vector<Rank> rnklst;

void Rnk()  //对所有的学生进行排名
{
    rnklst.clear();
    for(int i=0; i<n; i++){
        if(flag[i]){
            rnklst.push_back(Rank(i, stu[i].tot));
        }
    }
    sort(rnklst.begin(), rnklst.end());
    int s = rnklst.size();
    for(int i=0; i<s; i++){
        if(i!=0 && rnklst[i].tot==rnklst[i-1].tot){
            stu[rnklst[i].id].rnk = stu[rnklst[i-1].id].rnk;
        }else{
            stu[rnklst[i].id].rnk = i+1;
        }
    }
}

void Cls()   //统计每个班级和所有班级的各项数据
{
    for(int i=0; i<25; i++){
        cls[i] = Class();
    }
    for(int i=0; i<n; i++){
        if(flag[i]){
            int p = stu[i].cid;
            cls[p].num++;
            cls[0].num++;
            int pass = 0;
            for(int j=0; j<4; j++){
                cls[p].scores[j] += stu[i].scores[j];
                cls[0].scores[j] += stu[i].scores[j];
                if(stu[i].scores[j] >= 60){
                    cls[p].passed[j]++;
                    cls[0].passed[j]++;
                    pass++;
                }
                else{
                    cls[p].failed[j]++;
                    cls[0].failed[j]++;
                }
            }
            if(pass == 0){
                cls[p].overall[4]++;
                cls[0].overall[4]++;
            }else if(pass == 1){
                cls[p].overall[3]++;
                cls[0].overall[3]++;
            }else if(pass == 2){
                cls[p].overall[3]++;
                cls[p].overall[2]++;
                cls[0].overall[3]++;
                cls[0].overall[2]++;
            }else if(pass == 3){
                cls[p].overall[3]++;
                cls[p].overall[2]++;
                cls[p].overall[1]++;
                cls[0].overall[3]++;
                cls[0].overall[2]++;
                cls[0].overall[1]++;
            }else if(pass == 4){
                cls[p].overall[3]++;
                cls[p].overall[2]++;
                cls[p].overall[1]++;
                cls[p].overall[0]++;
                cls[0].overall[3]++;
                cls[0].overall[2]++;
                cls[0].overall[1]++;
                cls[0].overall[0]++;
            }
        }
    }
}

void Add()  //增加学生
{
    char tmpsid[15];
    int tmpcid;
    char tmpname[15];
    int tmpscores[4];
    while(true){
        printf("Please enter the SID, CID, name and four scores. Enter 0 to finish.\n");
        scanf("%s", tmpsid);
        if(strcmp(tmpsid, "0") == 0) break;
        scanf("%d%s%d%d%d%d", &tmpcid, tmpname, &tmpscores[0], &tmpscores[1], &tmpscores[2], &tmpscores[3]);
        int i;
        for(i=0; i<n; i++){
            if(flag[i] && strcmp(stu[i].sid, tmpsid)==0){
                printf("Duplicated SID.\n");
                break;
            }
        }
        if(i == n){
            stu[n] = Stu(tmpsid, tmpcid, tmpname, tmpscores);
            flag[n++] = true;
            Rnk();
            Cls();
        }
    }
}

void Remove()  //去掉某名学生的数据
{
    char tmp[15];
    while(true){
        printf("Please enter SID or name. Enter 0 to finish.\n");
        scanf("%s", tmp);
        if(strcmp(tmp, "0") == 0) break;
        int num = 0;
        for(int i=0; i<n; i++){
            if(flag[i] && (strcmp(stu[i].sid, tmp)==0 || strcmp(stu[i].name, tmp)==0)){
                flag[i] = false;
                num++;
            }
        }
        Rnk();
        Cls();
        printf("%d student(s) removed.\n", num);
    }
}

void Query()  //查找学生
{
    char tmp[15];
    while(true){
        printf("Please enter SID or name. Enter 0 to finish.\n");
        scanf("%s", tmp);
        if(strcmp(tmp, "0") == 0) break;
        for(int i=0; i<n; i++){
            if(flag[i] && (strcmp(stu[i].sid, tmp)==0 || strcmp(stu[i].name, tmp)==0)){
                printf("%d %s %d %s %d %d %d %d %d %.2lf\n", stu[i].rnk, stu[i].sid, stu[i].cid, stu[i].name, stu[i].scores[0], stu[i].scores[1], stu[i].scores[2], stu[i].scores[3], stu[i].tot, stu[i].ave);
            }
        }
    }
}

void ShowR()  //展示排名
{
    printf("Showing the ranklist hurts students' self-esteem. Don't do that.\n");
}

void ShowS()  //展示统计数据
{
    int tmp;
    printf("Please enter class ID, 0 for the whole statistics.\n");
    scanf("%d", &tmp);

    printf("Chinese\n");
    printf("Average Score: %.2lf\n", 1.0*cls[tmp].scores[0]/cls[tmp].num+1e-5);
    printf("Number of passed students: %d\n", cls[tmp].passed[0]);
    printf("Number of failed students: %d\n\n", cls[tmp].failed[0]);

    printf("Mathematics\n");
    printf("Average Score: %.2lf\n", 1.0*cls[tmp].scores[1]/cls[tmp].num+1e-5);
    printf("Number of passed students: %d\n", cls[tmp].passed[1]);
    printf("Number of failed students: %d\n\n", cls[tmp].failed[1]);

    printf("English\n");
    printf("Average Score: %.2lf\n", 1.0*cls[tmp].scores[2]/cls[tmp].num+1e-5);
    printf("Number of passed students: %d\n", cls[tmp].passed[2]);
    printf("Number of failed students: %d\n\n", cls[tmp].failed[2]);

    printf("Programming\n");
    printf("Average Score: %.2lf\n", 1.0*cls[tmp].scores[3]/cls[tmp].num+1e-5);
    printf("Number of passed students: %d\n", cls[tmp].passed[3]);
    printf("Number of failed students: %d\n\n", cls[tmp].failed[3]);

    printf("Overall:\n");
    printf("Number of students who passed all subjects: %d\n", cls[tmp].overall[0]);
    printf("Number of students who passed 3 or more subjects: %d\n", cls[tmp].overall[1]);
    printf("Number of students who passed 2 or more subjects: %d\n", cls[tmp].overall[2]);
    printf("Number of students who passed 1 or more subjects: %d\n", cls[tmp].overall[3]);
    printf("Number of students who failed all subjects: %d\n\n", cls[tmp].overall[4]);
}

void PrintMenu()  //打印菜单
{
    printf("Welcome to Student Performance Management System (SPMS).\n\n");
    printf("1 - Add\n");
    printf("2 - Remove\n");
    printf("3 - Query\n");
    printf("4 - Show ranking\n");
    printf("5 - Show Statistics\n");
    printf("0 - Exit\n\n");
}

int main()
{
    //freopen("in.txt", "r", stdin);
    n = 0;
    memset(flag, false, sizeof(flag));
    int s = 1;
    while(s){
        PrintMenu();
        scanf("%d", &s);
        switch(s){
        case 1:
            Add();
            break;
        case 2:
            Remove();
            break;
        case 3:
            Query();
            break;
        case 4:
            ShowR();
            break;
        case 5:
            ShowS();
            break;
        }
    }
    return 0;
}

想看书上的源代码的话看这 (^▽^)
https://github.com/aoapc-book/aoapc-bac2nd

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值