PAT甲级1016 Phone Bills

该博客介绍了一个Python程序,用于处理电话费用计算。程序首先读取每分钟的费率,然后处理多组通话记录,包括打电话和挂断的时间。记录可能存在错误,如打和挂次数不匹配。程序按人名和时间排序,并处理重复的通话,取最后一次打的电话时间和第一次挂的电话时间。计算总时间和费用,并输出每个人的通话详情及总金额。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1016 Phone Bills

题目大意:第一行给出每个时间段每分钟打电话的费用(美分,最后需要输出美元),接下来给出n组数据分别列出通话的人,时间,是打还是挂

注意:
不是所有记录都合法,打和挂数量不对应一定有错的。这里我是先按照人名,后按照时间顺序从小到大排列,若是碰到重复的打电话则取最后一次打的时间;若是碰到重复的挂电话则取第一次挂电话的时间

由于我之前用cppAC了一次于是这次用的是python,写的比较乱:

def calTimeBill(start,end):	#计算时间和费用
    global rate
    l_start=list(map(int,start.split(':')[1:]))
    s=(l_start[0]-1)*24*60+l_start[1]*60+l_start[2]
    total=sum(rate)*60
    bs=(l_start[0]-1)*total
    for i in range(l_start[1]):
        bs+=60*rate[i]
    bs+=rate[l_start[1]]*l_start[2]
    l_end=list(map(int,end.split(':')[1:]))
    e=(l_end[0]-1)*24*60+l_end[1]*60+l_end[2]
    be=(l_end[0]-1)*total
    for i in range(l_end[1]):
        be+=60*rate[i]
    be+=rate[l_end[1]]*l_end[2]
    return (e-s,(be-bs)/100)

def cmp(s):	#比较函数
    name=s[0][0]
    l=list(map(int,s[1][0].split(':')))
    return (name,l[0],l[1],l[2],l[3])

def total(name,l):   #计算总时间和总金钱
    t_time=0  #每个时间段的时间
    t_bill=0.0  #每个时间段的费用
    month=int(l[0][0].split(':')[0])    #月份
    print("{:s} {:02d}".format(name,month))
    total_bill=0.0
    for i in range(0,len(l),2):
        print(l[i][0][3:],l[i+1][0][3:],end=" ")
        (t_time,t_bill)=calTimeBill(l[i][0],l[i+1][0])
        print("{:d} ${:.2f}".format(t_time,t_bill))
        total_bill+=t_bill
    print("Total amount: $%.2f" % total_bill)

rate=list(map(int,input().split()))
n=int(input())
l=[]
lasting={}	#记录每个人打电话持续时间,以name:[(time,status)]格式存储
for i in range(n):
    l.append(list(zip(input().split())))
l.sort(key=lambda x:cmp(x))   #按照时间从小到大排序
for i in l:
    name=i[0][0]    #姓名
    status=i[2][0]  #on或off状态
    t=i[1][0]   #时间
    if lasting.get(name)==None: #若该姓名还未出现过
        if status=="off-line":	#第一次出现的人不可能是挂电话
            continue
        else:
            lasting[name]=[(t,status)]
    else:   #该姓名已经出现
        if lasting[name][-1][1]!=status:    #此人上一次状态与这次不一样则收录
            lasting[name].append((t,status))
        else:
            if status=="on-line":   #若此人上一次状态与这次一样且是on则将上一次收录的结果覆盖(取最后一次打电话的时间)
                lasting[name][-1]=(t,status)
            elif status=="off-line":    #若此人上一次状态与这次一样且是off则忽略此次记录(取第一次挂电话的时间)
                continue
key=lasting.keys()
for i in key:
    if len(lasting[i])%2!=0:	#若是奇数则最后一次时间是多出来的
        lasting[i].pop()
    if len(lasting[i])!=0:	#这里要判断是否为空
        total(i,lasting[i])


### PAT 甲级 真题 1172 解析 对于PAT甲级真题1172,该题目名为“Phone Bill”,主要考察字符串处理以及简单的数据结构应用能力。此题目的背景设定为客户通话记录统计问题。 #### 题目描述 给定一组电话号码及其对应的拨打时间和持续时间,计算每位用户的月账单总额。每条通话记录包含三个字段:电话号码、起始时间和结束时间。要求按照输入顺序输出每个客户的总费用,并保留两位小数[^1]。 #### 输入格式说明 - 第一行给出正整数N (≤10^5),表示有N次呼叫; - 接下来N行,每行提供一次呼叫的信息:“手机号码 起始时刻 结束时刻”。其中,“起始时刻”和“结束时刻”的格式均为HH:MM:SS; #### 输出格式说明 - 对于每一个客户,先打印其手机号码,再跟上冒号和空格,最后是当月话费金额(精确到分),单位为元人民币RMB。 #### 示例代码实现 ```cpp #include <iostream> #include <map> #include <iomanip> using namespace std; int main() { int n; cin >> n; map<string, double> bills; while(n--) { string number; char start_time[9], end_time[9]; scanf("%s %s %s", &number[0], start_time, end_time); // Convert time strings to seconds since midnight. sscanf(start_time, "%*d:%*d:%d", &start_seconds); sscanf(end_time, "%*d:%*d:%d", &end_seconds); // Calculate duration and update bill accordingly. int duration = end_seconds - start_seconds; if(duration > 0){ bills[number] += ceil((double)duration / 60 * 0.01); } } for(auto& entry : bills){ cout << entry.first << ": " << fixed << setprecision(2) << entry.second << endl; } return 0; } ``` 上述C++程序实现了对输入数据的读取与处理逻辑,通过`<map>`容器来存储并累加各个用户的通话时长及相应费用。需要注意的是,在实际比赛中应当更加严谨地验证输入的有效性和边界条件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值