PAT1016. Phone Bills

试题请参见: http://pat.zju.edu.cn/contests/pat-a-practise/1016

题目概述

系统会记录每个客户的通话情况, 会告诉你每个时间段(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;


    // Input
    for ( 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);
    }


    // Process
    for ( 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;
        }
    }


    //Output
    for ( 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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值