【TopCoder SRM 157 DIV 1】 Salary 解题报告
来源:互联网 发布:thinkphp网站源码下载 编辑:程序博客网 时间:2024/06/07 02:31
本来想把原题给贴过来的,后来看到人家有版权保护,在网上搜了一下,好像也没有人在博客中贴过原题,为避免麻烦,就不copy人家原题了。
【题目大意】
公司按照每小时 wage 元给员工发工资,员工上班打卡记录一个时间,下班记录一个时间,时间格式为 "hh:mm:ss"。其中,18:00:00 到 23:59:59 和 00:00:00 到 05:59:59 之间算加班时间,工资为1.5倍。计算工资时,分钟和秒都换算成小时来计算,最终的工资取整数,舍弃后面的小数。
【函数格式】
int howMuch(vector <string> arrival, vector <string> departure, int wage)
【注意】
arrival和departure元素个数一样,且arrival[0]<departure[0]<arrival[1]<departure[1]等等。
【解题思路】
思路不难,只是时间区间判断比较麻烦,有两个时间关键点06:00:00和18:00:00。
【我的代码】
class Salary {public:int compareTime(int hh1, int mm1, int ss1, int hh2, int mm2, int ss2) {if (hh1 > hh2 || (hh1 == hh2 && mm1 > mm2) || (hh1 == hh2 && mm1 == mm2 && ss1 > ss2)) {return 1;}if (hh1 < hh2 || (hh1 == hh2 && mm1 < mm2) || (hh1 == hh2 && mm1 == mm2 && ss1 < ss2)) {return -1;}return 0;}double duringTime(int hh1, int mm1, int ss1, int hh2, int mm2, int ss2) {double time = 0;if (ss2 >= ss1) {time += (ss2 - ss1) / 3600.0;} else {time += (ss2 + 60 - ss1) / 3600.0;mm2 -= 1;}if (mm2 >= mm1) {time += (mm2 - mm1) / 60.0;} else {time += (mm2 + 60 - mm1) / 60.0;hh2 -= 1;}time += hh2 - hh1;return time;}int howMuch(vector <string> arrival, vector <string> departure, int wage) {int beginHour, endHour, beginMinute, endMinute, beginSecond, endSecond;stringstream ss;double total = 0;for (int i = 0; i < arrival.size(); i++) {string time1 = arrival[i];ss.clear();ss << time1.substr(0, 2);ss >> beginHour;ss.clear();ss << time1.substr(3, 2);ss >> beginMinute;ss.clear();ss << time1.substr(6, 2);ss >> beginSecond;string time2 = departure[i];ss.clear();ss << time2.substr(0, 2);ss >> endHour;ss.clear();ss << time2.substr(3, 2);ss >> endMinute;ss.clear();ss << time2.substr(6, 2);ss >> endSecond;if (compareTime(beginHour, beginMinute, beginSecond, 6, 0, 0) < 0) {if (compareTime(endHour, endMinute, endSecond, 6, 0, 0) < 0) {total += duringTime(beginHour, beginMinute, beginSecond, endHour, endMinute, endSecond) * wage * 1.5;} else if (compareTime(endHour, endMinute, endSecond, 6, 0, 0) >= 0&& compareTime(endHour, endMinute, endSecond, 18, 0, 0) < 0) {total += duringTime(beginHour, beginMinute, beginSecond, 6, 0, 0) * wage * 1.5;total += duringTime(6, 0, 0, endHour, endMinute, endSecond) * wage;} else if (compareTime(endHour, endMinute, endSecond, 18, 0, 0) >= 0) {total += duringTime(beginHour, beginMinute, beginSecond, 6, 0, 0) * wage * 1.5;total += duringTime(6, 0, 0, 18, 0, 0) * wage;total += duringTime(18, 0, 0, endHour, endMinute, endSecond) * wage * 1.5;}} else if (compareTime(beginHour, beginMinute, beginSecond, 18, 0, 0) < 0) {if (compareTime(endHour, endMinute, endSecond, 18, 0, 0) < 0) {total += duringTime(beginHour, beginMinute, beginSecond, endHour, endMinute, endSecond) * wage;} else if (compareTime(endHour, endMinute, endSecond, 18, 0, 0) >= 0) {total += duringTime(beginHour, beginMinute, beginSecond, 18, 0, 0) * wage;total += duringTime(18, 0, 0, endHour, endMinute, endSecond) * wage * 1.5;}} else {total += duringTime(beginHour, beginMinute, beginSecond, endHour, endMinute, endSecond) * wage * 1.5;}}return (int)total;}};
首先是字符串转换成时分秒整数值。两个自定义函数功能分别为:比较两个时间点先后,主要是和两个关键时间点06:00:00和18:00:00比较;计算两个时间点之间的小时数。
然后一大段逻辑判断,判断员工工作时间是不是在00:00:00和06:00:00之间、06:00:00和18:00:00之间、18:00:00和00:00:00之间,还是说跨时间段。
由于基础不好,代码写得比较啰嗦,欢迎大家改进。【高手代码】
class Salary {public:int howMuch(vector <string> arrival, vector <string> departure, int wage) {long long total = 0;for(int i = 0; i < arrival.size(); i++) {total += calc(departure[i]) - calc(arrival[i]);}return total * wage / 7200;}long long calc(string t) {for (int i = 0; i < t.size(); i++) {if (t[i] == ':') {t[i] = ' ';}}stringstream sstream(t);int hh, mm, ss;sstream >> hh >> mm >> ss;int total = 3600 * hh + 60 * mm + ss;long long x = 0;for (int i = 0; i < total; i++) {if (i >= 0 && i < 6 * 3600) {x += 3;} else if (i >= 18 * 3600 && i < 24 * 3600) {x += 3;} else {x += 2;}}return x;}};
一眼就可以看出,人家的代码要简洁很多。这个代码的思路是计算24小时的每一秒拿工资的倍数,然后把工作时间的所有秒的倍数累加起来。由于加班时间工资是1.5倍,为计算方便,都乘以2,也就是说正常工作时间是2倍工资,加班时间是3倍工资,最后再除以2。所以代码中返回值处有个除以7200。
【学习点】
1. 关于时间的计算,换算成秒计算比时分秒操作方便;
2. 关于取整,可以先放大倍数,最后再缩小到原来,这样不容易丢失精度。
- 【TopCoder SRM 157 DIV 1】 Salary 解题报告
- topcoder srm 623解题报告
- Topcoder SRM 584 DIV2 解题报告
- Topcoder SRM 583 DIV2 解题报告
- topcoder srm 519 div 1
- Topcoder SRM 597 DIV 1
- Topcoder SRM 596 DIV 1
- Topcoder SRM 598 DIV 1
- TopCoder SRM 144 DIV 1
- TopCoder SRM 657 DIV 1
- TopCoder SRM 669 DIV 1
- Topcoder SRM 585 DIV2 解题报告 //缺1000
- topcoder SRM 503报告
- topcoder SRM div 2 level 1
- topcoder SRM 144 DIV 1 by First_Blood
- TopCoder SRM 612 DIV 1 450 SpecialCells
- topcoder SRM 348 Div.1 LostParentheses
- topcoder srm 677 DIV 1 300
- Android 编辑彩信,加入几页铃声,预览暂停界面,铃声名字不见了
- PowerDesigner创建文件时找不到DBMS列表
- NYOJ 47 过河问题
- NGUI扩展:为面板(Panel)添加自定义图片遮罩
- 文件下载出现中文乱码问题
- 【TopCoder SRM 157 DIV 1】 Salary 解题报告
- Java编程中“为了性能”尽量要做到的一些地方
- 6 个重构方法可帮你提升 80% 的代码质量
- AxureRP7.0基础教程 部件详解 图片/Image
- Android TDD平台插入双卡时,查看允许返回发送报告的选项,去掉勾选,不起作用
- C++中动态申请二维数组
- MFC中CScrollView类的使用以及CScrollView的双缓冲绘图
- 黑马程序员—一个美女程序员面试经历,不要羡慕姐,姐只是个传说!
- 九种js弹出对话框的方法总结