题目大意:
给出24h中每个小时区间内的资费(cents/minute),并给出N条通话记录,每条通话记录都记录了姓名、当前时刻(月:日:时:分)以及其属于通话开始(on-line) 或是通话结束(off-line)。现在需要对每个人的有效通话记录进行资费计算,有效通话记录是指同一个用户能够配对的所有on-line和off-line,而这样的配对需要满足:在按时间顺序排列后,两条配对的on-line和off-line对应时间内不允许出现其他的on-line或off-line的记录。输出要求:按姓名的字典序从小到大的顺序输出存在有效通话记录的用户。对单个用来说,需要输出他的姓名、账单月份(题目保证单个用户的所有记录都在同一个月产生)以及有效通话记录的时长和花费,最后输出他的总资费。
算法思路:
由于需要对每一个用户的账单进行输出,所以这里采用按照用户分组的方式来处理,由于输出也是需要按照字典序进行输出,所以这里先对所有的记录进行排序,对于名字不同的按照字典序排序,对于名字相同的记录按照每条记录的产生时间从前往后排序。然后处理每一组用户,使用2个指针work_pointer和next_person,分别表示当前用户的工作指针和下一个用户的第一条记录的位置。在work_pointer和next_person之间的就是同一个用户。那么在同一用户之间只需要找到一对,也就是紧紧挨着的2条记录,上一条为on-line,下一条为off-line,这样就找到了一条有效记录,有可能会出现没有有效记录的情况,这里使用一个标识ispaired
来记录是否有有效记录,在生成账单的时候设置为true,在当前用户遍历完毕的时候,如果ispaired为true,那么就保留当前人的账单。并且更新work_pointer为next_person,进入下一个用户的遍历。
时间的处理:
对于月份使用一个变量month就可以保存,然后对于天,小时和分全部转化为分钟来进行处理。
一条有效记录费用的计算:
这里给出2种方法,第一种就是采用加法,每加一分钟就累计当前小时的每一分钟的费用,然后直到开始时间和结束时间相等。代码就是如下的
callOneRecordCharge函数:
// 计算一条记录的收费
double callOneRecordCharge(int start_time,int end_time){
int sdd = start_time/24/60;
int shh = start_time%(24*60)/60;
int smm = start_time%(24*60)%60;
double sum = 0;
while (start_time
第二种方法采用减法,先计算从00:00:00到开始时间的花费,然后计算从00:00:00到结束时间的花费,然后让后者减去前者得到开始时间到结束时间的花费,代码如下:
double cal(int time){//计算00:00:00到time的花费
int dd = time/(24*60);//天
int hh = time%(24*60)/60;//小时
int mm = time%60;//分钟
double charge = 0;//00:00:00到time时间的花费
for(int i=0;i
这里采用了第一种方法
注意点:
1、资费的输出需要进行单位换算,即把cent换算为dollar,所以结果要除以100。
2、同一用户的通话记录按照时间先后进排序输出。这里使用了map就是会自动排序
3、测试点1,2,3都是在判断是否会输出无效记录,这里给出一组数据供参考,如果输出了3个用户就是错的。
10 10 10 10 10 10 20 20 20 15 15 15 15 15 15 15 20 30 20 15 15 10 10 10
10
CYLL 01:01:06:01 on-line
CYLL 01:28:16:05 on-line
CYJJ 01:01:07:00 off-line
CYLL 01:01:08:03 on-line
CYJJ 01:01:05:59 on-line
aaa 01:01:01:03 on-line
aaa 01:02:00:01 on-line
CYLL 01:28:15:41 on-line
aaa 01:05:02:24 on-line
aaa 01:04:23:59 on-line
4、输出格式中一般整型都得是%02d的格式,但是单条记录的花费直接用%d,总花费得用%.2f
5、work_pointer提交结果:
AC代码:
#include