UVA12412 师兄帮帮忙 A Typical Homework (a.k.a Shi Xiong Bang Bang Mang) 题解
阅读原文时间:2023年07月10日阅读:1

自己去看题面去。

算不上很繁琐的一道大模拟。

首先,既然是输出 \(0\) 才退出,那么在此之前程序应当会执行菜单 \(\Rightarrow\) 子操作 \(\Rightarrow\) 菜单 \(\Rightarrow\) 子操作 \(\Rightarrow\dots\) 直到你在菜单里面输入 \(0\)。因此我们可以写出这样的主体框架:

while(1) {
    Menu();
    int x; read(x);
    if(!x) break;
    if(x == 1) Add();
    else if(x == 2) Remove();
    else if(x == 3) Query();
    else if(x == 4) Ranking();
    else if(x == 5) Statistics();
}

然后我们对于每个函数具体将一下里头要注意的东西。

Part 0 Menu

这一部分确实比较容易,毕竟你只需要输出题目给你的那一大段东西即可。但要注意换行的问题!洛谷上面的样例吃掉了所有的空行,而 UVA 又是狠抓这里的,因此你需要按照题目要求的那样输出,不能够多或者少!这里建议直接对着题面复制粘贴输出内容,以防自己打的时候出错。另外,输入整数的时候需要时刻判断是否应该退出系统。

Part 1 Add

首先先输入一个字符串(不要全输入进去),用来判断其是否为 0 从而进一步判断是否应该退出。如果没有退出的话,之后就把所有的学生信息全部输入完整,然后再直接暴力查数据库里面还没有被删除的学生中是否有学生的学号和新学生的学号冲突,冲突了直接跳过这一次添加操作,否则直接加入数据库里面并标记没有被删除。

另外,为了在之后的 Query 部分中输出学生的排名较方便,我们每次改变数据库之后先把这些学生按照总分从大到小排序(注意还要将没有被删除的同学放在前面,以免出错),然后直接从第一个学生开始计算他的排名。具体地,我们有一个计数器 \(cnt\),初始值为 \(1\),每算完一个学生的排名它就加 \(1\)。然后我们只需要判断当前学生的总分是否和上一个学生的总分相等,相等的话他的排名就是上一个学生的排名,否则他的排名即为计数器 \(cnt\) 当前的值。计算完之后,一定要把数据库还原成初始状态,即按照学生加入数据库的先后顺序排序,以方便之后 Query 部分的输出。

Part 2 Remove

删除学生时直接暴力查数据库里面所有还没有被删除的学生当中,是否有学号或者名字对应上的,对应上了直接标记为被删除,并且计入删除总人数里面去。

同样的,在删除完以后同样也需要进行一次排序,具体见 Add 部分的介绍。

Part 3 Query

同样地,我们直接暴力查数据库里面所有还没有被删除的学生当中,是否有学号或者名字对应上的,对应上了的直接按题目要求输出所有信息即可。注意在输出平均分的时候,可能会有精度误差,可以像题目里面所提示的那样,加上一个很小的数以减小精度误差。

Part 4 Ranking

根据题目要求输出那一段我个人觉得感同身受的文字即可。

Part 5 Statistics

输入完班级号之后,我们直接查所有学生中班级号对应上的学生的信息(当然,如果输入的班级号是 \(0\),那么就查所有学生的信息),统计题目需要我们统计的东西然后按照题目要求的那样输出就行了。注意以下两点:

  • 建议还是直接复制粘贴题目里面的输出内容,以防自己打的时候出错(这题的大小写和标点符号的添加情况尤其恶心,一定要特别注意)。
  • 和 Query 部分相同,在输出平均分的时候,可能会有精度误差,可以像题目里面所提示的那样,加上一个很小的数以减小精度误差。

那么这道大模拟就写完了。还有什么不懂得欢迎在评论区留言或者直接私信我。

剩下的就是愉快地模拟了。

namespace Solution {
    const double eps = 1e-5;
    int cnt;
    struct node {
        string sid, name;
        int id, cid, s1, s2, s3, s4, del, rk, sum;
        int pass1, pass2, pass3, pass4, passnum;
    }a[1007];

    ib cmp1(const node& t1, const node& t2) {
        if(t1.del != t2.del) return t1.del < t2.del;
        return t1.sum > t2.sum;
    }
    ib cmp2(const node& t1, const node& t2) {
        if(t1.del != t2.del) return t1.del < t2.del;
        return t1.id < t2.id;
    }
    iv Sort() {
        sort(a + 1, a + cnt + 1, cmp1);
        int currk = 1, exactrk = 1;
        F(int, i, 1, cnt) {
            if(a[i].del) break;
            if(i != 1 && a[i].sum != a[i - 1].sum) exactrk = currk;
            a[i].rk = exactrk, currk++;
        }
        sort(a + 1, a + cnt + 1, cmp2);
    }
    iv Menu() {
        puts("Welcome to Student Performance Management System (SPMS).");
        puts("");
        puts("1 - Add");
        puts("2 - Remove");
        puts("3 - Query");
        puts("4 - Show ranking");
        puts("5 - Show Statistics");
        puts("0 - Exit");
        puts("");
    }
    iv Add() {
        while(1) {
            string newsid, newname;
            int newcid, news1, news2, news3, news4;
            puts("Please enter the SID, CID, name and four scores. Enter 0 to finish.");
            cin >> newsid;
            if(newsid == "0") break;
            cin >> newcid >> newname, read(news1, news2, news3, news4);
            node tmp; int fl = 1;
            tmp.sid = newsid, tmp.cid = newcid;
            tmp.name = newname, tmp.s1 = news1;
            tmp.s2 = news2, tmp.s3 = news3;
            tmp.s4 = news4, tmp.del = 0;
            tmp.sum = tmp.s1 + tmp.s2 + tmp.s3 + tmp.s4;
            tmp.pass1 = (tmp.s1 >= 60);
            tmp.pass2 = (tmp.s2 >= 60);
            tmp.pass3 = (tmp.s3 >= 60);
            tmp.pass4 = (tmp.s4 >= 60);
            tmp.passnum = tmp.pass1 + tmp.pass2 + tmp.pass3 + tmp.pass4;
            F(int, i, 1, cnt) if(!a[i].del && a[i].sid == newsid) {puts("Duplicated SID."), fl = 0; break;}
            if(fl) tmp.id = ++cnt, a[cnt] = tmp;
            Sort();
        }
        return;
    }
    iv Remove() {
        while(1) {
            string t;
            puts("Please enter SID or name. Enter 0 to finish.");
            cin >> t;
            if(t == "0") break;
            int delcnt = 0;
            F(int, i, 1, cnt) if(!a[i].del && (a[i].sid == t || a[i].name == t)) a[i].del = 1, delcnt++;
            printf("%d student(s) removed.\n", delcnt);
            Sort();
        }
        return;
    }
    iv Query() {
        while(1) {
            string t;
            puts("Please enter SID or name. Enter 0 to finish.");
            cin >> t;
            if(t == "0") break;
            F(int, i, 1, cnt) if(!a[i].del && (a[i].sid == t || a[i].name == t)) {
                cout << a[i].rk << ' ' << a[i].sid << ' ' << a[i].cid << ' ' << a[i].name << ' ' << a[i].s1 << ' ' << a[i].s2 << ' ' << a[i].s3 << ' ' << a[i].s4 << ' ' << a[i].sum << ' ';
                printf("%.2lf\n", a[i].sum / 4.0 + eps);
            }
        }
        return;
    }
    iv Ranking() {
        puts("Showing the ranklist hurts students' self-esteem. Don't do that.");
        return;
    }
    iv Statistics() {
        puts("Please enter class ID, 0 for the whole statistics.");
        int qcid; read(qcid);
        int num = 0, sum = 0, passcnt = 0, failcnt = 0;
        F(int, i, 1, cnt) if(!a[i].del && (a[i].cid == qcid || !qcid)) {
            num++, sum += a[i].s1;
            if(a[i].pass1) passcnt++;
            else failcnt++;
        }
        puts("Chinese");
        printf("Average Score: %.2lf\n", sum * 1.0 / num + eps);
        printf("Number of passed students: %d\n", passcnt);
        printf("Number of failed students: %d\n", failcnt);
        puts("");
        num = 0, sum = 0, passcnt = 0, failcnt = 0;
        F(int, i, 1, cnt) if(!a[i].del && (a[i].cid == qcid || !qcid)) {
            num++, sum += a[i].s2;
            if(a[i].pass2) passcnt++;
            else failcnt++;
        }
        puts("Mathematics");
        printf("Average Score: %.2lf\n", sum * 1.0 / num + eps);
        printf("Number of passed students: %d\n", passcnt);
        printf("Number of failed students: %d\n", failcnt);
        puts("");
        num = 0, sum = 0, passcnt = 0, failcnt = 0;
        F(int, i, 1, cnt) if(!a[i].del && (a[i].cid == qcid || !qcid)) {
            num++, sum += a[i].s3;
            if(a[i].pass3) passcnt++;
            else failcnt++;
        }
        puts("English");
        printf("Average Score: %.2lf\n", sum * 1.0 / num + eps);
        printf("Number of passed students: %d\n", passcnt);
        printf("Number of failed students: %d\n", failcnt);
        puts("");
        num = 0, sum = 0, passcnt = 0, failcnt = 0;
        F(int, i, 1, cnt) if(!a[i].del && (a[i].cid == qcid || !qcid)) {
            num++, sum += a[i].s4;
            if(a[i].pass4) passcnt++;
            else failcnt++;
        }
        puts("Programming");
        printf("Average Score: %.2lf\n", sum * 1.0 / num + eps);
        printf("Number of passed students: %d\n", passcnt);
        printf("Number of failed students: %d\n", failcnt);
        puts("");
        int cnt4 = 0, cnt3 = 0, cnt2 = 0, cnt1 = 0, cnt0 = 0;
        F(int, i, 1, cnt) if(!a[i].del && (a[i].cid == qcid || !qcid)) {
            cnt4 += (a[i].passnum == 4);
            cnt3 += (a[i].passnum == 3);
            cnt2 += (a[i].passnum == 2);
            cnt1 += (a[i].passnum == 1);
            cnt0 += (a[i].passnum == 0);
        }
        puts("Overall:");
        printf("Number of students who passed all subjects: %d\n", cnt4);
        printf("Number of students who passed 3 or more subjects: %d\n", cnt3 + cnt4);
        printf("Number of students who passed 2 or more subjects: %d\n", cnt2 + cnt3 + cnt4);
        printf("Number of students who passed 1 or more subjects: %d\n", cnt1 + cnt2 + cnt3 + cnt4);
        printf("Number of students who failed all subjects: %d\n", cnt0);
        puts("");
        return;
    }

    iv Main() {
        while(1) {
            Menu();
            int x; read(x);
            if(!x) break;
            if(x == 1) Add();
            else if(x == 2) Remove();
            else if(x == 3) Query();
            else if(x == 4) Ranking();
            else if(x == 5) Statistics();
        }
        return;
    }
}