Welcome

首页 / 软件开发 / 数据结构与算法 / 记录每个客户的通话情况并计算出每个客户的月账单情况

记录每个客户的通话情况并计算出每个客户的月账单情况2015-02-11

题目概述

系统会记录每个客户的通话情况, 会告诉你每个时间段(00:00~01:00, 01:00~02:00, ...)的通话费用. 要求计算出每个客户的月账单情况.

输入

每个输入包含测试用例, 每个测试用例包含两部分: 每个时间段的通话费用(分(cent)/分钟)和每个客户的通话情况.

通话费用由24个非负整数组成, 代表了24小时内每个小时的通话费用.

接下来N(<= 1000)行是客户的通话记录. 每条记录由以下项目组成: 客户的姓名, 时间和日期(格式为month:day:hour:minute)和在线情况("on-line" 或者 "off-line")

对于每一个测试用例, 都是在同一个月内的记录. 按时间排序后, 所有"on-line"的记录之后都会跟着一条"off-line"的记录. 任何"on-line"记录之后没有"off-line"与之匹配的记录都可以被忽略; 同样地, 任何"off-line"记录之前没有"on-line"记录的记录也可以被忽略. 测试数据保证至少有一条"on-line"和"off-line"匹配的记录, 并且没有一个客户在同一时间和其他两个客户通话. 时间是24小时制的.

输出

对于每一个测试用例, 你需要打印每个客户的月账单情况.

客户按照字母顺序表排列, 对于每个客户, 你需要打印如下内容:

第1行:     客户姓名 账单对应月份

第2行起: 用户每个通话的起始和结束时间, 以及该次通话的费用

最后1行: 通话的总费用

解题思路

由于通话记录是无序的, 因此我们对每个客户用一个vector保存当前通话情况(on-line和off-line)的时间; 当全部输入结束后, 对vector进行排序.

对于每个客户的通话记录做匹配, 求出每段对话的通话时间和费用, 存储在另一个vector中.

为了方便索引, 将用户的姓名和通话情况保存在map中, 其中用户姓名作为主键.

在编码过程中, 计算每次通话的的金额是个复杂的地方.

遇到的问题

第一次提交, 有2个点WA.

问题出在, 若一个客户该月没有(合法的)通话记录, 则不输出该客户的任何信息.

源代码

#include <iostream>#include <iomanip>#include <fstream>#include <algorithm>#include <string>#include <vector>#include <map>const int NUMBER_OF_HOURS = 24;struct Record {std::string time;bool isOnline;};struct Call {std::string startTime;std::string endTime;int totalTime;int amount;};struct Customer {std::vector<Record> records;std::vector<Call> callRecords;int totalAmount;};int atoi(char digit0, char digit1) {return (digit0 - "0") * 10 + (digit1 - "0");}int getTotalTime(std::string time) {int day = atoi(time[3], time[4]);int hour = atoi(time[6], time[7]);int minute = atoi(time[9], time[10]);return day * 24 * 60 + hour * 60 + minute;}int getTotalMinute(const std::string& startTime, const std::string& endTime) {return getTotalTime(endTime) - getTotalTime(startTime);}int getCallAmount(int* toll, const std::string& startTime, const std::string& endTime) {int startDay = atoi(startTime[3], startTime[4]);int endDay = atoi(endTime[3], endTime[4]);int startHour = atoi(startTime[6], startTime[7]);int endHour = atoi(endTime[6], endTime[7]);int startMinute = atoi(startTime[9], startTime[10]);int endMinute = atoi(endTime[9], endTime[10]);int callAmount = 0;for ( int i = startDay; i <= endDay; ++ i ) {int lowerBound = 0, upperBound = 23;if ( i == startDay ) {lowerBound = startHour;} if ( i == endDay ) {upperBound = endHour;}for ( int j = lowerBound; j <= upperBound; ++ j ) {callAmount += toll[j] * 60;}}callAmount -= toll[startHour] * startMinute + toll[endHour] * (60 - endMinute);return callAmount;}int getTotalAmount(const std::vector<Call>& callRecords) {int totalAmount = 0;for ( size_t i = 0; i < callRecords.size(); ++ i ) {totalAmount += callRecords[i].amount;}return totalAmount;}void getCallRecords(int* toll, Customer& customer) {std::string previousTime;bool previousIsOnline = false;for ( size_t i = 0; i < customer.records.size(); ++ i ) {if ( !customer.records[i].isOnline && previousIsOnline ) {Call call;call.startTime = previousTime;call.endTime = customer.records[i].time;call.totalTime = getTotalMinute(call.startTime, call.endTime);call.amount = getCallAmount(toll, call.startTime, call.endTime);customer.callRecords.push_back(call);previousIsOnline = false;} else if ( customer.records[i].isOnline ) {previousTime = customer.records[i].time;previousIsOnline = true;}}customer.totalAmount = getTotalAmount(customer.callRecords);}bool compareRecords(const Record& record1, const Record& record2) {return record1.time < record2.time;}int main() {using std::cin;// std::ifstream cin;// cin.open("input.txt");// int toll[NUMBER_OF_HOURS] = {0};int n = 0;std::map<std::string, Customer> customers;// Inputfor ( int i = 0; i < NUMBER_OF_HOURS; ++ i ) {cin >> toll[i];}cin >> n;for ( int i = 0; i < n; ++ i ) {std::string name, time, isOnline;cin >> name >> time >> isOnline;Record record;record.time = time;record.isOnline = ( isOnline == "on-line" );customers[name].records.push_back(record);}// Processfor ( auto itr = customers.begin(); itr != customers.end(); ++ itr ) {std::sort(itr->second.records.begin(), itr->second.records.end(), compareRecords);getCallRecords(toll, itr->second);}std::string currentMonth;for ( auto itr = customers.begin(); itr != customers.end(); ++ itr ) {if ( itr->second.callRecords.size() != 0 ) {currentMonth = itr->second.callRecords[0].startTime.substr(0, 2);break;}}//Outputfor ( auto itr = customers.begin(); itr != customers.end(); ++ itr ) {if ( itr->second.callRecords.size() != 0 ) {std::cout << itr->first << " " << currentMonth << std::endl;for ( size_t i = 0; i < itr->second.callRecords.size(); ++ i ) {std::cout << itr->second.callRecords[i].startTime.substr(3, 8) << " " << itr->second.callRecords[i].endTime.substr(3, 8) << " "<< itr->second.callRecords[i].totalTime << " $"<< std::fixed << std::setprecision(2) << (itr->second.callRecords[i].amount / 100.0)<< std::endl;}std::cout << "Total amount: $" << std::fixed << std::setprecision(2) <<(itr->second.totalAmount / 100.0) << std::endl;}}return 0;}