Phone Bills【PAT 1016题】--- 电话账单结算
题目链接:http://pat.zju.edu.cn/contests/pat-practise/1016
以前在POJ上也见过类似的题,当时还不会qsort,菜的一米,遇到大数据还用链表做,还没等把输入处理完成,就已经头大的发麻了,看来我还是有一点进步的。
这道题我开了个record数组,记录所有的账单,第一步先根据字母表顺序将账单排序分类,在此要大大的感谢一把qsort,它可以数组内指定位置和指定长度进行排序,所以我就没有把账单记录分开存到各个客户名下,而是用qsort分割排序,和单独处理单个客户的账单效果一模一样。第二步,根据客户名称作为id,单独对当前处理的客户记录进行时间排序,然后处理,这道题逻辑有点小复杂,和昨天的那个银行排队一样,都属于无关算法而着重逻辑的,到最后的计算时间和费用有点棘手,不过把思路整清楚就OK了。
这道题要注意的陷阱就一点:1.如果客户A的账单记录没有任何一对是合法的,则客户A什么信息都不输出,估计电信局就这样设计的,一年应该可以省不少木材。^_^
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 typedef struct 6 { 7 char name[22];//名字 8 int month;//月份 9 int day;//天 10 int hour;//时 11 int minute;//分 12 char tag[10];//on-line or off-line 13 }record; 14 15 int n; 16 record *rd; 17 int rate[24];//费率 18 int count, start;//记录当前处理的这个用户的记录数目,和当前这个用户的第一条记录位置 19 double totalCharge;//该用户该月的费用合计 20 21 double charge(int sday, int shour, int sminute, int eday, int ehour, int eminute)//计算一条有效电话记录的时长和费用,并返回费用 22 { 23 double cost = 0; 24 long time = 0; 25 26 while(sday < eday)//先让天相等 27 { 28 time += (60 - sminute); 29 cost += (60 - sminute) * rate[shour]; 30 sminute = 0; shour ++;//分化成0,时加1 31 time += 60 * (24 - shour); 32 while(shour < 24) 33 { 34 cost += 60 * rate[shour]; 35 shour ++; 36 } 37 shour = 0; sday ++;//时化成0,天加1 38 }//天此时相等,时分为00:00 39 while(shour < ehour)//再让时相等 40 { 41 time += (60 - sminute); 42 cost += (60 - sminute) * rate[shour]; 43 sminute = 0; shour ++; 44 } 45 time += (eminute - sminute); 46 cost += rate[ehour] * (eminute - sminute); 47 48 printf("%ld $%.2lf\n", time, cost / 100); 49 50 return cost / 100; 51 } 52 53 void totalCount()//数出当前要处理的客户的总记录数目 54 { 55 int i; 56 for(i = start + 1; i < n; i ++) 57 { 58 if(strcmp(rd[i].name, rd[i - 1].name) != 0) 59 { 60 break; 61 } 62 else 63 { 64 count ++; 65 } 66 } 67 } 68 69 int comp_name(const void *a, const void *b) 70 { 71 record c = *(record *)a; 72 record d = *(record *)b; 73 74 75 if(strcmp(c.name, d.name) <= 0) return -1; 76 else return 1; 77 } 78 79 int comp_time(const void *a, const void *b) 80 { 81 record c = *(record *)a; 82 record d = *(record *)b; 83 84 if(c.day < d.day) return -1; 85 else if(c.day > d.day) return 1; 86 else 87 { 88 if(c.hour < d.hour) return -1; 89 else if(c.hour > d.hour) return 1; 90 else 91 { 92 if(c.minute < d.minute) return -1; 93 else return 1; 94 } 95 } 96 } 97 98 int main() 99 {100 int i;101 int flag;//1应该出现offline, 0应该出现online102 int onpos;//记录最近有效的on-line记录位置,为了算出charge103 int sign;//0表示该客户名字和月份还没有输出,1表示已输出104 105 106 while(scanf("%d", &rate[0]) != EOF)107 {108 for(i = 1; i < 24; i ++)109 {110 scanf("%d", &rate[i]);111 }112 scanf("%d", &n);113 rd = (record *)malloc(n * sizeof(record));114 for(i = 0; i < n; i ++)115 {116 scanf("\n%s %d:%d:%d:%d %s", rd[i].name, &rd[i].month, &rd[i].day, &rd[i].hour, &rd[i].minute, rd[i].tag);117 }118 qsort(rd, n, sizeof(record), comp_name);//先将记录按字母表顺序分类119 count = 1; start = 0; totalCount(); sign = 0;120 while(start < n)//整个记录表还没处理完121 {122 qsort(rd + start, count, sizeof(record), comp_time);123 flag = 0;124 totalCharge = 0;125 for(i = start; i < start + count; i ++)//处理该客户126 {127 if(flag == 0)//期待出现online,如果是offline跳过128 {129 if(rd[i].tag[1] == 'f')//off-line130 {131 continue;132 }133 else//on-line134 {135 onpos = i;136 flag = 1;137 }138 }139 else//期待出现offline,如果是online则更新onpos140 {141 if(rd[i].tag[1] == 'n')//on-line142 {143 onpos = i;144 }145 else//off-line146 {147 if(sign == 0)148 {149 printf("%s %02d\n", rd[start].name, rd[start].month);150 sign = 1;151 }152 printf("%02d:%02d:%02d %02d:%02d:%02d ", rd[onpos].day, rd[onpos].hour, rd[onpos].minute, rd[i].day, rd[i].hour, rd[i].minute);153 totalCharge += charge(rd[onpos].day, rd[onpos].hour, rd[onpos].minute, rd[i].day, rd[i].hour, rd[i].minute);154 flag = 0;155 }156 }157 }158 if(sign == 1)159 {160 printf("Total amount: $%.2lf\n", totalCharge);161 }162 start += count; count = 1; totalCount(); sign = 0;163 }164 }165 return 0;166 }
转载于:https://www.cnblogs.com/Rafy/archive/2012/03/20/2408013.html
Phone Bills【PAT 1016题】--- 电话账单结算相关推荐
- PAT 1016 Phone Bills (25分) 逻辑较为复杂 sort() + map
题目 A long-distance telephone company charges its customers by the following rules: Making a long-dis ...
- PAT乙级题库踩坑实录
PAT乙级题库踩坑实录 [截止2021.7.28乙级题库已经全部AC] 题目名称: 1030 完美数列 (25 分) 测试点3踩坑 每次取m后,不用从m后第一个元素开始判断是否大于mp,直接从m后第m ...
- 软件测试——电话账单收费
对电话账单来说,春季和秋季的标准时间与夏时制时间的转换会带来有意思的问题.春季,这种转换发生在(3 月末,4 月初的)星期日凌晨 2:00 时,这时时钟要设置为凌晨 3:00 时.对称的转换通常发生在 ...
- pat真题1002 写出这个数C语言解法和java解法
pat真题1002 写出这个数C语言解法和java解法 读入一个正整数 n,计算其各位数字之和,用汉语拼音写出和的每一位数字. 输入格式: 每个测试输入包含 1 个测试用例,即给出自然数 n 的值.这 ...
- PAT刷题之乙级1033 旧键盘打字
目录 PAT刷题之乙级1033(cpp) 题目描述 输入格式 输出格式 输入样例 输出样例 问题分析 代码实现 运行实现 PAT刷题之乙级1033(cpp) 题目描述 旧键盘上坏了几个键,于是在敲一段 ...
- 【PAT】PAT甲级题库所有题解(持续更新中...)
题解: 本文为导航页,一些希望刷PAT甲级的玩家可以来看看,我会持续更新所有题目的题解(取决于我做到哪儿了(doge)) 题号按照PAT官网给出的标注 题目: 链接 标签 1001 A+B Forma ...
- 【PAT乙级题库】全套总结
我将难度分为三个等级: 简单 中等 难 简单的做一次足以,做再多遍也无任何的意义. 中等的可以多刷几遍 难的多刷几遍 目录 1001 害死人不偿命的(3n+1)猜想[简单] 1002 写出这个数 (2 ...
- C语言PAT刷题 - 1020 月饼
作者的话:若有朋友复制代码去PAT试着运行遇到问题的: 1.可能是格式问题,可以先把从本站复制的代码粘贴到记事本,再把记事本里的代码复制,然后粘贴到PAT的代码区,提交本题回答,应该就可以了: 2.可 ...
- C语言PAT刷题 - 1019 数字黑洞
作者的话:若有朋友复制代码去PAT试着运行遇到问题的: 1.可能是格式问题,可以先把从本站复制的代码粘贴到记事本,再把记事本里的代码复制,然后粘贴到PAT的代码区,提交本题回答,应该就可以了: 2.可 ...
- PAT做题过程中的一些方法技巧总结
1.格式化输出整数 例子: 7766 - 6677 = 1089 9810 - 0189 = 9621 9621 - 1269 = 8352 8532 - 2358 = 6174 printf(&qu ...
最新文章
- Vue + Bootstrap|Element UI——模态框被遮罩层遮盖问题解决方案
- 维护没有源代码的遗留 Java 项目
- 正则表达式matlab,正则表达式中一个word的匹配 @MATLAB - 优秀的Free OS(Linux)版 - 北大未名BBS...
- android compress函数,Linux Kernel(Android) 加密算法小结(cipher、compress、digest)
- 编程珠玑笔记-第12章习题
- 【非功能性测试】软件测试之非功能性测试有哪些?
- 2019计算机专业英语国家线,2019英语一国家线多少
- Mtk ALPS Led驱动的加载过程
- 面向对象设计,ORM,NHIBERNATE杂谈(有感)
- rime 简体中文 linux,Rime (简体中文)
- King of Fighters 2003 全人物发招表(转)
- 使用Minifly打造基于视觉感知的跟踪无人机
- 浅谈To B与To C的区别
- SVN误删的文件可以恢复
- Coinversation Protocol (铸币协议)简版白皮书及网站
- 自然数的皮亚诺公理系統
- daad转换器实验数据_DAAD留德日记作者:20分钟我拿到了德企总部的实习offer
- oracle asru,最佳实践之二:VSP+ORACLE
- 员工强烈要求不买社保怎么规避风险 企业不交社保怎样规避风险
- Yahoo前端的35条优化军规