1 条题解
-
0
自动搬运
来自洛谷,原作者为

Eason_AC
Remember? / AFOed on 2022.6.14 / 彻底死咯搬运于
2025-08-24 22:29:46,当前版本为作者最后更新于2021-03-10 13:44:34,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
Update
- 修复了一个笔误。
Content
太长了,请直接跳转回题面查看。
数据范围:,,,,,。
变量含义同原题面。
Solution
很烦人的一道大模拟。
既然题目说成绩分五部分,那我们的程序也分五部分进行:
Part 1 体育课专项成绩
这个直接输入完就往总分数里面加,不需要多讲。
Part 2 长跑成绩
读入的时候运用了一个小 trick:我们知道
scanf是可以按照格式读入的,所以直接用"%d'%d\""的格式读入即可【注意!在字符串里面想要打入"需要在其前面加一个反斜杠(\)】。然后,直接拿分钟数和秒数去对比显然有点麻烦,我们不妨直接将其转化为秒数。我们都知道 分钟有 秒,所以将读入的时间直接转化成秒数就是 。再去比对题目中的表格。把题目中的表格中的时间转化成秒数,得到一个新的表格(建议去题解界面查看):
长跑得分 男生/秒 女生/秒 然后直接一波 if-else 搞定。
Part 3 阳光长跑
本题的重头戏,因为要考虑的情况实在是太多了。
首先要将对应的长跑数据转入到对应的人中。这里如果直接开数组的话,显然, 显然空间爆炸,所以考虑开个
vector,读入的时候将所有的数据储存到一个结构体变量当中,再直接转入到对应的人中去。这里又有一个 trick:我们通过 STL 中的
map,将所有的人的学号映射到其在输入数据中的编号,这样处理起来就很简单,不需要再去暴力循环找了。所有的长跑原始数据都转移到对应的人上面去后,我们注意到,在每个人底下的长跑原始数据并不一定是有序的,然而题目当中 开始时间需与上条合法记录的结束时间间隔 小时以上(包含 小时) 这个条件要求我们一定要对这些数据进行一定程度的排序。
既然这样那就对这些数据排序吧,这里你可以直接在结构体下面定义重载运算符,也可以直接弄一个
compare函数,都能够起到自定义排序的作用。这道题目对于阳光长跑的合法条件实在是多,但我们只能够一个一个去对了,建议按照以下次序:
- 如果男生跑步路程 米,女生跑步路程 米,那么这条记录就不合法。
- 否则,如果跑步速度 ,或者 ,或者平均步幅 ,或者总休息时间 秒(同样也是用的处理长跑成绩时的 trick),那么这条记录不合法。
- 否则,如果目前记录是这位同学的第 条长跑记录,那么这条记录就已经是合法的了,计入计数器。
- 如果这条记录不是第 条记录,那么继续往下判断。提取出上条记录的结束时间的年、月、日、时、分、秒和目前记录的开始时间的年、月、日、时、分、秒。
- 如果月份不一样,那么判断是否超过了 个月。超过了一个月的话这条记录就是合法的。
- 否则这两条记录就是相邻月份的,然后我们再看上次合法记录的结束时间是不是在上一个月的最后一天,且该条记录的开始时间是不是在本月的第一天。如果不是,那么这条记录就是合法的。
- 否则,这两天其实只相隔一天,我们再看看它们的间隔时间是否大于 小时,也就是 秒即可。月份不一样的就算处理完了。
- 接下来,如果这两个日期不在同一天,我们再看相隔天数,如果超过 天,那么这个记录就是合法的。
- 否则,那么这两个日期相隔天数正好一天,我们只需要看这两个记录的间隔时间是否大于 小时即可。天份不一样的情况也处理完了。
- 最后,这两个日期正好是在同一天,直接拿两个时间相减看时间是否大于 小时即可。
合法记录的数量就这样搞定了。那么从这里开始就很简单了!首先,这一部分的分数只需要一波 if-else 就能够搞定。
Part 4 体质测试成绩
只需要看给出的字符是否是
P,是的话分数 ,否则不变。Part 5 大一专项计划
这里又分为两部分。
Part 5.1 出勤
由题目可知,次数就等于班级训练营的参加次数和在 Part 3 里面处理完的阳光长跑合法记录次数的和。得到出勤次数之后又是一波 if-else 搞定分数。
Part 5.2 期末检测
这个直接输入完就往总分数里面加,不需要多讲。
最后的输出等第也是直接一波 if-else 搞定。
那么这道题目也就算做完了。最后友情提示,做这道题目的时候一定要沉下心来一步一步去做!不然稍有个一不留神 分就全没有了。
下面给出具体代码实现,配有详细注释,仅供参考,请勿抄袭。
Code
struct sunnyrun { int y, m, d, hs, ms, ss, ht, mt, st, rest, step; double l; bool operator < (const sunnyrun& tmp) const { //按照记录开始时间排序 if(y != tmp.y) return y < tmp.y; else if(m != tmp.m) return m < tmp.m; else if(d != tmp.d) return d < tmp.d; else if(hs != tmp.hs) return hs < tmp.hs; else if(ms != tmp.ms) return ms < tmp.ms; return ss < tmp.ss; } }; struct student { int mf, s, a, b, pf, f, c, score, num2, num; ll p; vector<sunnyrun> q; /* mf:1 表示男生,0 表示女生 pf:1 表示通过,0 表示没有通过 */ }a[10007]; const int mm[17] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; double l; map<ll, int> vis; inline int calcms(int a, int b) {return a * 60 + b;} // 分秒形式的时间转换成秒 inline int calchms(int a, int b, int c) {return a * 3600 + b * 60 + c;} // 时分秒形式的时间转换成秒 inline int s1(int x) {return a[x].s;} //直接计入分数 inline int s2(int x) { if(a[x].mf) { if(calcms(a[x].a, a[x].b) <= 750) return 20; else if(calcms(a[x].a, a[x].b) > 750 && calcms(a[x].a, a[x].b) <= 780) return 18; else if(calcms(a[x].a, a[x].b) > 780 && calcms(a[x].a, a[x].b) <= 810) return 16; else if(calcms(a[x].a, a[x].b) > 810 && calcms(a[x].a, a[x].b) <= 840) return 14; else if(calcms(a[x].a, a[x].b) > 840 && calcms(a[x].a, a[x].b) <= 870) return 12; else if(calcms(a[x].a, a[x].b) > 870 && calcms(a[x].a, a[x].b) <= 910) return 10; else if(calcms(a[x].a, a[x].b) > 910 && calcms(a[x].a, a[x].b) <= 950) return 8; else if(calcms(a[x].a, a[x].b) > 950 && calcms(a[x].a, a[x].b) <= 990) return 6; else if(calcms(a[x].a, a[x].b) > 990 && calcms(a[x].a, a[x].b) <= 1030) return 4; else if(calcms(a[x].a, a[x].b) > 1030 && calcms(a[x].a, a[x].b) <= 1080) return 2; else return 0; // 如果上面的都不符合一定要记得 return 0!不然可能会 RE } else { if(calcms(a[x].a, a[x].b) <= 400) return 20; else if(calcms(a[x].a, a[x].b) > 400 && calcms(a[x].a, a[x].b) <= 417) return 18; else if(calcms(a[x].a, a[x].b) > 417 && calcms(a[x].a, a[x].b) <= 434) return 16; else if(calcms(a[x].a, a[x].b) > 434 && calcms(a[x].a, a[x].b) <= 451) return 14; else if(calcms(a[x].a, a[x].b) > 451 && calcms(a[x].a, a[x].b) <= 470) return 12; else if(calcms(a[x].a, a[x].b) > 470 && calcms(a[x].a, a[x].b) <= 485) return 10; else if(calcms(a[x].a, a[x].b) > 485 && calcms(a[x].a, a[x].b) <= 500) return 8; else if(calcms(a[x].a, a[x].b) > 500 && calcms(a[x].a, a[x].b) <= 515) return 6; else if(calcms(a[x].a, a[x].b) > 515 && calcms(a[x].a, a[x].b) <= 530) return 4; else if(calcms(a[x].a, a[x].b) > 530 && calcms(a[x].a, a[x].b) <= 540) return 2; else return 0; // 同上 } } inline int s3(int x) { int cnt = 0, flg1 = 0; sunnyrun lst; sort(a[x].q.begin(), a[x].q.end()); //按照记录开始时间排序 int sze = a[x].q.size(); F(i, 0, sze - 1) { sunnyrun now = a[x].q[i]; if(now.l < (a[x].mf ? 3.0 : 1.5)) continue; //路程不达标,不合法 int ts = calchms(now.hs, now.ms, now.ss), tt = calchms(now.ht, now.mt, now.st); double v = now.l * 1000.0 / (tt - ts), pe = now.l * 1000.0 / now.step; if(v < 2 || v > 5 || pe > 1.5 || now.rest > 270) continue; //速度、步幅、总休息时间中任意一个不达标,不合法 if(!flg1) {flg1 = 1, lst = a[x].q[i], cnt++; continue;} //以上条件都达标且是第一个记录,合法 ts = calchms(lst.ht, lst.mt, lst.st), tt = calchms(now.hs, now.ms, now.ss); //开始时间和结束时间 if(now.m != lst.m) { //不是一个月 if(now.m - 1 != lst.m) {lst = now, cnt++; continue;} //间隔超过一个月,合法 else { if(mm[lst.m] != lst.d || now.d != 1) {lst = now, cnt++; continue;} //上条合法记录的结束时间是上个月的最后一天、该条记录的开始时间是这个月的第一天当中有一条不符合,合法 else if(86400 + tt - ts < 21600) continue; //间隔只有一天,并且间隔时间小于 6 小时,不合法 } } else if(now.d != lst.d) { //不是同一天 if(now.d - 1 != lst.d) {lst = now, cnt++; continue;} //间隔天数超过 1 天,合法 else if(86400 + tt - ts < 21600) continue; //间隔只有一天,并且间隔时间小于 6 小时,不合法 } else if(tt - ts < 21600) continue; //间隔时间小于 6 小时,不合法 lst = now, cnt++; //合法 } a[x].num2 = cnt; //计入次数 if(a[x].num2 >= 21) return 10; else if(a[x].num2 >= 19 && a[x].num2 <= 20) return 9; else if(a[x].num2 >= 17 && a[x].num2 <= 18) return 8; else if(a[x].num2 >= 14 && a[x].num2 <= 16) return 7; else if(a[x].num2 >= 11 && a[x].num2 <= 13) return 6; else if(a[x].num2 >= 7 && a[x].num2 <= 10) return 4; else if(a[x].num2 >= 3 && a[x].num2 <= 6) return 2; else return 0; } inline int s4(int x) {return a[x].pf ? 10 : 0;} //直接计入分数 inline int s5(int x) { a[x].num = a[x].c + a[x].num2; if(a[x].num >= 18) return 5 + a[x].f; //出勤次数和期末检测成绩综合判断 else if(a[x].num >= 15 && a[x].num <= 17) return 4 + a[x].f; else if(a[x].num >= 12 && a[x].num <= 14) return 3 + a[x].f; else if(a[x].num >= 9 && a[x].num <= 11) return 2 + a[x].f; else if(a[x].num >= 6 && a[x].num <= 8) return 1 + a[x].f; else return a[x].f; } int main() { int n = Rint; F(i, 1, n) { a[i].p = Rll; char ch[2]; scanf("%s", ch); a[i].mf = (ch[0] == 'M'); //性别是否是男 a[i].s = Rint; scanf("%d'%d\"", &a[i].a, &a[i].b); //强制按照 a'b" 的格式读入 a,b scanf("%s", ch); a[i].pf = (ch[0] == 'P'); a[i].f = Rint, a[i].c = Rint; vis[a[i].p] = i; //建立映射关系 } int m = Rint; F(i, 1, m) { sunnyrun ins; //待插入元素 int date = Rint; ins.y = date / 10000, ins.m = date % 10000 / 100, ins.d = date % 100; ll px = Rll; int id = vis[px]; //映射出该学生在输入数据中的编号 scanf("%d:%d:%d %d:%d:%d", &ins.hs, &ins.ms, &ins.ss, &ins.ht, &ins.mt, &ins.st); //强制按照 hh:mm:ss hh:mm:ss 的格式读入该条记录的开始时间和结束时间的时分秒 scanf("%lf", &ins.l); //路程 int ax, bx; scanf("%d'%d\"", &ax, &bx); ins.rest = calcms(ax, bx), ins.step = Rint; //强制按照 a'b" 的格式读入 a,b a[id].q.push_back(ins); //插入对应结构体元素下的 vector 中 } F(i, 1, n) { a[i].score = s1(i) + s2(i) + s3(i) + s4(i) + s5(i); //五个部分的分数合计 printf("%lld %d ", a[i].p, a[i].score); if(a[i].score >= 95 && a[i].score <= 100) puts("A"); //判断等第 else if(a[i].score >= 90 && a[i].score < 95) puts("A-"); else if(a[i].score >= 85 && a[i].score < 90) puts("B+"); else if(a[i].score >= 80 && a[i].score < 85) puts("B"); else if(a[i].score >= 77 && a[i].score < 80) puts("B-"); else if(a[i].score >= 73 && a[i].score < 77) puts("C+"); else if(a[i].score >= 70 && a[i].score < 73) puts("C"); else if(a[i].score >= 67 && a[i].score < 70) puts("C-"); else if(a[i].score >= 63 && a[i].score < 67) puts("D+"); else if(a[i].score >= 60 && a[i].score < 63) puts("D"); else puts("F"); } return 0; }
- 1
信息
- ID
- 6548
- 时间
- 1000ms
- 内存
- 500MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者