UVA - 12412 A Typical Homework
/* 这题其实不难,而且很贴近生活啊!等ACM题刷累了的时候,不妨把这个代码再多加些功能,写成一个小小的项目试试,我觉得会挺有意义 体现了的知识点: 为了避免浮点数的误差,一般在按小数点输入之前,要先将它和一个较小的数EPS(通常用1e-5)相加 打脸了...WA了将近一天,各种调试和找错,整整找了一天,没错,就是整整一天,不是上学的一天,是暑假的一整天,什么都不做专门调这道题的那种一天,好几次都崩溃到想放掉这道题...想着,WA就WA吧,反正真正比赛的时候,应该不会出这种题目 (这脸打得也太响了,我本来还想着,这道题看思路似乎挺简单,要不就不做了,先自学些数据结构等别的ACM题,结果...太轻视这题了啊!~) 但是想了想,不能这样啊,凡事只有0次和无数次的区别...如果我这次因为一直WA就放弃了,下次就可以因为这个数据结构/算法没学过,这道题太难,这道题一直没思路又没题解根本做不出...等等各种其他的理由放弃掉别的题。要放弃可以有很多理由~可是既然给自己划定了某个目标,就不要畏难,死磕也要磕到底,哪怕是付出再多时间,也一定要磕下来...战线可以拉长,不求在最近就弄明白,可是绝对不能在心里告诉自己:我不管了,太难了,这道题我就是做不出来了... 嗯,对自己还是不能放太多水,平时放的水,最后都会在WA时,变成自己深沉的泪水,hhh~ */
/* 版本1 这个题目其实挺好理解,我就不解释我的代码了,来讲讲我究竟是怎么WA的吧! UVA的输出数据里面,应该有格式或者中西文标点的错误,因为我直接把UVA里面的这句输出复制下来 "Showing the ranklist hurts students’ self-esteem. Don’t do that." 提交代码的时候,就是WA 而我自己敲了这句以后,就只是改了这句,改为 "Showing the ranklist hurts students' self-esteem. Don't do that." 就AC了...惊不惊喜,意不意外,我会说,没想到还有这个天坑吗! T^T...做这道题一定要注意注意再小心,至少这句话,不要直接从UVA的样例输出里面复制 (我会说复制,本来就是为了避免出现,中西文标点等看不出差别的问题,UVA的数据居然还这样坑我,真是天坑啊!卒~) 吐槽完毕,上代码...可以说是很艰难的AC了...唉 (对了,最终真正找到这个bug,还要多亏了命令行的神操作..下次专门写一篇博文讲下,我究竟是怎么发现,错误居然在这里的...最关键的突破点,是因为利用了命令行的txt比较功能) 话说,当时没想到还真的有这个操作,抱着试试的心态随手一搜,居然真的有...搜索引擎可真是个好东西啊!hhhhhhh....(大家多多百度谷歌吧,真的很多时候会有意外的收获呢!) 从此以后,我觉得我就可以借助重定向和这个比较功能,很方便地加各种输出语句来调试了...ohyeah!!~ 不知道什么时候能来填(如何利用命令行发现隐藏很深的WA原因)这个坑,就先把这个命令行神操作的网址放着好了 https://jingyan.baidu.com/article/19020a0a1dd04a529c284272.html */
#include <iostream> #include <iomanip> #include <string> #include <cstring> #include <algorithm> #include <cstdio> //#define debug using namespace std; const int maxn = 1e5; const double EPS = 1e-5; int n = 0; int CID, _score[4], sum; string SID, name, s; const string course[] = {"Chinese", "Mathematics", "English", "Programming"}; const string words[] = {"Number of students who failed all subjects: ", "Number of students who passed 1 or more subjects: ", "Number of students who passed 2 or more subjects: ", "Number of students who passed 3 or more subjects: ", "Number of students who passed all subjects: "}; struct student { int CID, score[5]; // Chinese, Math, English, Programming, total bool del; double average; string name, SID; }stu[maxn]; void Print_Menu() { cout << "Welcome to Student Performance Management System (SPMS)." << endl << endl << "1 - Add" << endl << "2 - Remove" << endl << "3 - Query" << endl << "4 - Show ranking" << endl << "5 - Show Statistics" << endl << "0 - Exit" << endl << endl; } int valid() // 检查是否合法,如果输入的SID已经输入过了,则该输入不合法,因而不处理该输入 { for (int i = 0; i < n; i++) if (!stu[i].del) if (stu[i].SID == SID) return 0; return 1; } int Rank (int k) { int cnt = 0; for (int i = 0; i < n; i++) { if ( !stu[i].del && stu[i].score[4] > stu[k].score[4] ) cnt++; } return cnt + 1; } void Add() { while (1) { sum = 0; cout << "Please enter the SID, CID, name and four scores. Enter 0 to finish." << endl; cin >> SID; if (SID == "0") return; cin >> CID >> name; for (int i = 0; i < 4; i++) { cin >> _score[i]; sum += _score[i]; } if (!valid()) cout << "Duplicated SID." << endl; else { stu[n].SID = SID; stu[n].CID = CID; stu[n].name = name; for (int i = 0; i < 4; i++) stu[n].score[i] = _score[i]; stu[n].score[4] = sum; stu[n].average = sum * 1.0 / 4 + EPS; stu[n].del = false; n++; } } } void Remove() { while (1) { cout << "Please enter SID or name. Enter 0 to finish." << endl; cin >> s; if (s == "0") break; int cnt = 0; for (int i = 0; i < n; i++) { if ( !stu[i].del && (stu[i].SID == s || stu[i].name == s) ) { stu[i].del = true; ++cnt; } } cout << cnt << " student(s) removed." << endl; } } void Query() { while (1) { cout << "Please enter SID or name. Enter 0 to finish." << endl; cin >> s; if (s == "0") return; for (int i = 0; i < n; i++) { char c = ' '; if ( !stu[i].del && (stu[i].SID == s || stu[i].name == s) ) { cout << Rank(i) << c << stu[i].SID << c << stu[i].CID << c << stu[i].name << c; for (int j = 0; j < 5; j++) cout << stu[i].score[j] << c; cout << fixed << setprecision(2) << stu[i].average << endl; } } } } void Statistics() { cout << "Please enter class ID, 0 for the whole statistics." << endl; int cid, i, j, passed, failed, total, cnt, cnt1; cin >> cid; int p[5]; // p[i]记录通过了i门课程的学生 char c;// c == ' ' memset(p, 0, sizeof(p)); // 每次调用都要清空p,p[i]代表了当前指定的范围的学生中,有p[i]或以上的同学通过了该课程 if (!cid) //cid == 0, 0 for the whole statistics,枚举所有学生,不论其班级是什么 { for (int i = 0; i < 4; i++) // 枚举科目 { passed = 0, failed = 0, total = 0, cnt = 0; for (j = 0; j < n; j++) { if (!stu[j].del) // 枚举没被删除的同学 { cnt++; total += stu[j].score[i]; if (stu[j].score[i] >= 60) passed++; else failed++; } } cout << course[i] << endl << "Average Score: " << fixed << setprecision(2) << (cnt ? total * 1.0 / cnt + EPS : 0) << endl << "Number of passed students: " << passed << endl << "Number of failed students: " << failed << endl << endl; } for (int i = 0; i < n; i++) // 枚举没被删除的学生 { if (!stu[i].del) { cnt1 = 0; for (int j = 0; j < 4; j++) // 枚举他上的每门课程,计算多少门及格 { if (stu[i].score[j] >= 60) cnt1++; } //更新统计通过i门课(i [0, 4]) 的学生数 if (!cnt1) p[0]++; else for (int k = 1; k <= cnt1; k++) p[k]++; } } cout << "Overall:" << endl; for (int i = 4; i >= 0; i--) cout << words[i] << p[i] << endl; cout << endl; } else // 仅找班级号与cid相同的,且没被删除的学生 { for (int i = 0; i < 4; i++) { passed = failed = total = cnt = 0; for (int j = 0; j < n; j++) { if (!stu[j].del && stu[j].CID == cid) { cnt++; total += stu[j].score[i]; if (stu[j].score[i] >= 60) passed++; else failed++; } } cout << course[i] << endl << "Average Score: " << fixed << setprecision(2) << (cnt ? total * 1.0 / cnt + EPS : 0) << endl << "Number of passed students: " << passed << endl << "Number of failed students: " << failed << endl << endl; } for (int i = 0; i < n; i++) // 枚举没被删除的,且在指定班级的所有学生 { if (!stu[i].del && stu[i].CID == cid) { cnt1 = 0; for (int j = 0; j < 4; j++) // 枚举他上的每门课程,计算多少门及格 { if (stu[i].score[j] >= 60) cnt1++; } //更新统计通过i门课(i [0, 4]) 的学生数 if (!cnt1) p[0]++; else for (int k = 1; k <= cnt1; k++) p[k]++; } } cout << "Overall:" << endl; for (int i = 4; i >= 0; i--) cout << words[i] << p[i] << endl; cout << endl; } } int main() { cin.tie(0); cin.sync_with_stdio(false); #ifdef debug freopen("E:\\in.txt", "r", stdin); freopen("E:\\out.txt", "w", stdout); #endif // n = 0; int choice; bool flag = true; while(flag) { Print_Menu(); cin >> choice; switch(choice) { case 0: flag = false; break; case 1: Add(); break; case 2: Remove(); break; case 3: Query(); break; case 4: cout << "Showing the ranklist hurts students' self-esteem. Don't do that." << endl; break; case 5: Statistics(); break; } } #ifdef debug fclose(stdin); fclose(stdout); #endif return 0; }
/* 版本2 版本2与版本1的不同点是: 1. 合并了删除操作和查询操作的大部分代码。因为删除删除操作和查询的输入是一样的,并且,操作上也有大部分的重叠 2. 输出班级信息的部分,改为了两个函数,并且,将指定班级的输出和所有班级的输出合并了,因此只需要在特定的有选择语句的地方,除了判断输入数字是否与学生的班级号相等,再额外加上判断输入数字是否为0(因为为0时表示输出所有班级的信息,因而不再需要考虑学生的班级是否符合要求,直接全加上即可)...因而,合并了所有班级和指定班级的情况,大大精简了代码 又及,这个改进思路是从这个blog上看到的,然后我再以我最初敲好的代码,借鉴这个思路,作了一些简化和修改 http://blog.csdn.net/kun768/article/details/43816501 (据说还是汝佳老师的源代码),而且真是很简洁啊!一开始看到这道题的时候,我还以为不到将近200行一定搞不定,没想到...果然汝佳老师的思路就十分清晰,很清楚什么操作可以合并部分代码,什么情况可以合并大部分代码,因此代码也就简洁优美了很多 */
#include <iostream> #include <iomanip> #include <string> #include <cstring> #include <algorithm> #include <cstdio> //#define debug using namespace std; const int maxn = 1e5; const double EPS = 1e-5; int n = 0; int CID, _score[4], sum; string SID, name, s; const string course[] = {"Chinese", "Mathematics", "English", "Programming"}; const string words[] = {"Number of students who failed all subjects: ", "Number of students who passed 1 or more subjects: ", "Number of students who passed 2 or more subjects: ", "Number of students who passed 3 or more subjects: ", "Number of students who passed all subjects: "}; struct student { int CID, score[5]; // Chinese, Math, English, Programming, total bool del; double average; string name, SID; }stu[maxn]; void Print_Menu() { cout << "Welcome to Student Performance Management System (SPMS)." << endl << endl << "1 - Add" << endl << "2 - Remove" << endl << "3 - Query" << endl << "4 - Show ranking" << endl << "5 - Show Statistics" << endl << "0 - Exit" << endl << endl; } int valid() // 检查是否合法,如果输入的SID已经输入过了,则该输入不合法,因而不处理该输入 { for (int i = 0; i < n; i++) { if (!stu[i].del && stu[i].SID == s) return 0; } return 1; } int Rank (int k) { int cnt = 0; for (int i = 0; i < n; i++) { if ( !stu[i].del && stu[i].score[4] > stu[k].score[4] ) cnt++; } return cnt + 1; } void Add() { while (1) { cout << "Please enter the SID, CID, name and four scores. Enter 0 to finish." << endl; sum = 0; student in; cin >> s; in.SID = s; if (s == "0") break; cin >> in.CID >> in.name; for (int i = 0; i < 4; i++) { cin >> in.score[i]; sum += in.score[i]; } if (!valid()) cout << "Duplicated SID." << endl; else { in.score[4] = sum; in.average = sum / 4.0 + EPS; in.del = false; stu[n++] = in; } } } void DQ(const int op) // op代表操作,如果为 0,表明输出的是要删除的,如果为 1,表明输入的只是需要查询 { while (1) { cout << "Please enter SID or name. Enter 0 to finish." << endl; cin >> s; if (s == "0") break; int cnt = 0; for (int i = 0; i < n; i++) { if ( !stu[i].del && (stu[i].SID == s || stu[i].name == s) ) { if (!op) //删除 { stu[i].del = true; ++cnt; } else { char c = ' '; cout << Rank(i) << c << stu[i].SID << c << stu[i].CID << c << stu[i].name << c; for (int j = 0; j < 5; j++) cout << stu[i].score[j] << c; cout << fixed << setprecision(2) << stu[i].average << endl; } } } if (!op) cout << cnt << " student(s) removed." << endl; } } void output (const int no, const int type) { int sum = 0, cnt1 = 0, cnt2 = 0; for (int i = 0; i < n; i++) if ( !stu[i].del && (no == 0 || no == stu[i].CID) ) { sum += stu[i].score[type]; if (stu[i].score[type] >= 60) cnt1++; else cnt2++; } //#改到这里啦! cout << "Average Score: " << fixed << setprecision(2) <<( (cnt1 + cnt2 != 0)?(sum * 1.0 / (cnt1 + cnt2) + EPS ): 0 )<< endl << "Number of passed students: " << cnt1 << endl << "Number of failed students: " << cnt2 << endl << endl; } void Print() { int p[5]; memset(p, 0, sizeof(p)); cout << "Please enter class ID, 0 for the whole statistics." << endl; int num; cin >> num; for (int i = 0; i < 4; i++) { cout << course[i] << endl; output(num, i); } cout << "Overall:" << endl; for (int i = 0; i < n; i++) { if ( !stu[i].del && ( num == 0 || stu[i].CID == num ) ) { int tp = 0; for (int j = 0; j < 4; j++) if (stu[i].score[j] >= 60) tp++; if (!tp) p[0]++; else { for (int k = 1; k <= tp; k++) p[k]++; } } } for (int i = 4; i >= 0; i--) cout << words[i] << p[i] << endl; cout << endl; } int main() { cin.tie(0); cin.sync_with_stdio(false); #ifdef debug freopen("E:\\in.txt", "r", stdin); freopen("E:\\out.txt", "w", stdout); #endif int choice; bool flag = true; n = 0; while(flag) { Print_Menu(); cin >> choice; switch(choice) { case 0: flag = false; break; case 1: Add(); break; case 2: DQ(0); break; case 3: DQ(1); break; case 4: cout << "Showing the ranklist hurts students' self-esteem. Don't do that." << endl; break; case 5: Print(); break; } } #ifdef debug fclose(stdin); fclose(stdout); #endif return 0; }