【Python】PAT 甲級 A1016:Phone Bills(復(fù)雜模擬)
題目內(nèi)容
A long-distance telephone company charges its customers by the following rules:
Making a long-distance call costs a certain amount per minute, depending on the time of day when the call is made. When a customer starts connecting a long-distance call, the time will be recorded, and so will be the time when the customer hangs up the phone. Every calendar month, a bill is sent to the customer for each minute called (at a rate determined by the time of day). Your job is to prepare the bills for each month, given a set of phone call records.
Input Specification:
Each input file contains one test case. Each case has two parts: the rate structure, and the phone call records.
The rate structure consists of a line with 24 non-negative integers denoting the toll (cents/minute) from 00:00 - 01:00, the toll from 01:00 - 02:00, and so on for each hour in the day.
The next line contains a positive number (?1000), followed by? lines of records. Each phone call record consists of the name of the customer (string of up to 20 characters without space), the time and date (MM:dd:HH:mm
), and the word on-line
or off-line
.
For each test case, all dates will be within a single month. Each on-line
record is paired with the chronologically next record for the same customer provided it is an off-line
record. Any on-line
records that are not paired with an off-line
record are ignored, as are off-line
records not paired with an on-line
Output Specification:
For each test case, you must print a phone bill for each customer.
Bills must be printed in alphabetical order of customers' names. For each customer, first print in a line the name of the customer and the month of the bill in the format shown by the sample. Then for each time period of a call, print in one line the beginning and ending time and date (dd:HH:mm
), the lasting time (in minute) and the charge of the call. The calls must be listed in chronological order. Finally, print the total charge for the month in the format shown by the sample.
Sample Input:
Sample Output:
題目要點(diǎn)
本題 25 分,題干內(nèi)容多,各種細(xì)節(jié)繁復(fù),所以在做題時要認(rèn)真審題,將整個問題分成若干個模塊分別解決。除了輸入和輸出外,主要是三方面:①數(shù)據(jù)排序 ②篩選出可以“撥打-掛斷”配對的數(shù)據(jù) ③計算各個配對的費(fèi)用,再對各個用戶總費(fèi)用求和。
首先需要對數(shù)據(jù)進(jìn)行排序。將用戶按字典序排列,每個用戶的通話記錄再按照時間升序排列。由于輸入的時間格式比較嚴(yán)謹(jǐn),因此直接對字符串排序也是可以的。Python需要先對映射為鍵名的用戶排序,然后遍歷各個鍵值,將鍵值中存的多條通話記錄按時間排序。
很容易想到,尋找“撥打-掛斷”配對數(shù)據(jù)的方法是先將數(shù)據(jù)按時間遞增順序排列,然后利用循環(huán),判斷當(dāng)前狀態(tài)是是否是“撥打”且下一個狀態(tài)是否為“掛斷”,如果滿足,那么這兩條數(shù)據(jù)是配對的,如果不滿足,繼續(xù)查找。
使用while
語句處理起來更加方便,當(dāng)找到配對的數(shù)據(jù)時,由于數(shù)據(jù)是兩兩配對互不重復(fù),因此i
指針可以遞增2,這樣免去不必要的比較,可以提高效率。
計算電話費(fèi)用比較麻煩,因?yàn)檫€要考慮不同時段的單價,這里給出一種比較好理解的算法。首先建立小時對應(yīng)單價(美元/分鐘)長度為24的列表。然后將撥號時間start
和掛斷時間end
拆分成完整小時和不足小時(分鐘)兩類數(shù)據(jù)。
完整小時是從
start
到end
取整小時的左閉右開區(qū)間,比如02:00:01
到04:23:59
,我們只取小時數(shù),分別為 24×2+0=48 到 24×4+23=119,取48~119(不含119)之間的數(shù),分別求24的余數(shù),得到的即為每天對應(yīng)的小時,再以此為下標(biāo)取單價列表,對所有值求和,得到完整小時的總金額。在Python中列表推導(dǎo)式可以很容易實(shí)現(xiàn)這一過程。
不足小時是指剔除完整的小時后剩余的若干分鐘。比如掛斷時間
04:23:59
只取小時數(shù)是 24×4+23=119,那么還剩余59分鐘不足一小時,需要單獨(dú)累計。對于撥號時間02:00:01
,取小時數(shù)時實(shí)際上是看作一個完整的小時,因此過去的這1分鐘要扣除,因此要乘以負(fù)一。如下所示
各個測試點(diǎn)考察的點(diǎn)如下:
測試點(diǎn)0:簡單,沒有坑
測試點(diǎn)1:沒有成功撥打電話的用戶不予輸出,參考額外樣例1
測試點(diǎn)2:電話撥打掛斷在不同天的同一個小時,參考額外樣例2
測試點(diǎn)3:電話撥打掛斷在同一天的同一個小時,參考額外樣例2
額外樣例1
額外樣例2
Python源代碼
其它思路參考
柳神的另類思路:https://www.liuchuo.net/archives/2350
模塊化的C++代碼:https://segmentfault.com/a/1190000024570906
思路清晰的C代碼:https://www.cnblogs.com/caiyishuai/p/11296926.html