PAT 1016. Phone Bills

这道题目有两点要考虑的:1.如何匹配:其实条件很简单,只需要先按每个人的名字分组,然后按时间排序,只有当上一个记录是on-line且当前记录是off-line的时候,才匹配成功;2.如何计算一个时间段内的钱:因为是在一个月内的,所以可以写一个函数计算出从月初到某个时间点的所有花费,那么两个时间段减一减就可以了。也可以先把多出的分钟单独计算掉,然后就只计算小时的差距。

最坑爹的陷阱是:如果某个顾客的记录并没有匹配成功的,则说明信息都不显示。这我是网上看到的思路,我始终觉得题目里面没有这么说或者这么暗示。觉得坑爹!

Python代码:

import sys
import datetime
toll=[int(x) for x in raw_input().split()]

N=int(raw_input())
dic={}

timeFormat='%m:%d:%H:%M' #时间格式
for i in range(0,N):
	line=raw_input().split()
	if not dic.has_key(line[0]):
		dic[line[0]]=[]
	dic[line[0]].append((line[1],line[2])) #字典里面,每个人对应一个时间列表


def calc_day(): #计算一天所需要的钱
	sum=0
	for i in range(0,24):
		sum=sum+toll[i]*60
	return sum
def calc(beg,end):#计算从时间点beg到end的钱
	beg=datetime.datetime.strptime(beg,timeFormat)
	end=datetime.datetime.strptime(end,timeFormat)
	money=-beg.minute*toll[beg.hour]+end.minute*toll[end.hour]#先计算单出来的分钟
	aday=beg.hour
	bday=end.hour+24
	for i in range(aday,bday): #在计算从beg的hour到end的hour+24的钱,
                                   #加24是为了保证end.hour>beg.hour
		money=money+toll[i%24]*60
	money=money+(end.day-beg.day-1)*calc_day() #计算整天的钱
	min_diff=int((end-beg).total_seconds())/60 #计算分钟差
	return (min_diff,money/100.0)

for one in sorted(dic.keys()):
	dic[one].sort()
	lst=('','')
	lstItem=dic[one]
	sum=0
	isUsed=False #用于检测该用户是否至少有一次匹配成功的
	for it in lstItem:
		if lst[1]=='on-line' and it[1]=='off-line':
			if not isUsed:#如果有的话,则输出用户的信息
				isUsed=True
				print one,
				print lstItem[0][0][:2]
			beg=lst[0]
			end=it[0]
			(min_diff,money)=calc(beg,end)
			print beg[3:],end[3:],min_diff,'$%.2f'%(money) #输出时间段
			sum=sum+money
		lst=it
	if isUsed:#输出总额
		print 'Total amount: $%.2f'%(sum)

你可能感兴趣的:(phone,pat,1016,Bills)