首页 > 代码库 > PAT(A) 1016. Phone Bills (25)

PAT(A) 1016. Phone Bills (25)

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 N (<= 1000), followed by N 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" record. It is guaranteed that at least one call is well paired in the input. You may assume that no two records for the same customer have the same time. Times are recorded using a 24-hour clock.

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:

10 10 10 10 10 10 20 20 20 15 15 15 15 15 15 15 20 30 20 15 15 10 10 10
10
CYLL 01:01:06:01 on-line
CYLL 01:28:16:05 off-line
CYJJ 01:01:07:00 off-line
CYLL 01:01:08:03 off-line
CYJJ 01:01:05:59 on-line
aaa 01:01:01:03 on-line
aaa 01:02:00:01 on-line
CYLL 01:28:15:41 on-line
aaa 01:05:02:24 on-line
aaa 01:04:23:59 off-line

Sample Output:

CYJJ 01
01:05:59 01:07:00 61 $12.10
Total amount: $12.10
CYLL 01
01:06:01 01:08:03 122 $24.40
28:15:41 28:16:05 24 $3.85
Total amount: $28.25
aaa 01
02:00:01 04:23:59 4318 $638.80
Total amount: $638.80
#include <cstdio>
#include <cstring>
#include <string>           //map<string, int> parkTime;
#include <map>
#include <algorithm>
using namespace std;
const int maxn=10010;

struct Car{
    char id[8];             //车牌号(注:比较大小时用 strcmp(,) 
    int time;               //记录的 in or out 的时刻,以秒为单位
    char status[4];         //in or out
}all[maxn], valid[maxn];    //all为所有记录,valid为有效记录

//timeToInt(): 将时间转换为以秒为单位
int timeToInt(int hh, int mm, int ss){
    return hh*3600+mm*60+ss;
}
//cmp_byIdAndTime(): 先按车牌号字典序从小到大排序,相同的按时间从小到大排序
bool cmp_byIdAndTime(Car a, Car b){
    if( strcmp(a.id, b.id) )    return strcmp(a.id, b.id)<0;
    else    return a.time<b.time;
}
//cmp_byTime(): 按时间从小到大排序
bool cmp_byTime(Car a, Car b){
    return a.time<b.time;
}

int main()
{
    int n, k;           //n条记录,k个查询
    int hh, mm, ss;     //时,分,秒
    scanf("%d%d", &n, &k);
    for(int i=0; i<n; i++){
        scanf("%s %d:%d:%d %s", all[i].id, &hh, &mm, &ss, all[i].status);
        all[i].time=timeToInt(hh, mm, ss);  //转换为以秒为单位
    }
    //步骤(1): 按车牌号和时间排序
    sort(all, all+n, cmp_byIdAndTime);

    //步骤(2): 找有效记录,并记录某车牌号的最大总停留时间
    int num=0;                  //有效记录的条数(初始为0)
    int maxTime=-1;             //最长总停留时间(初始为-1)
    map<string, int> parkTime;  //车牌号 <-> 总停留时间 (即两者的映射
    parkTime[string]=int       //#include <string>

    for(int i=0; i<n-1; i++){                   //遍历所有记录
        if( !strcmp(all[i].id, all[i+1].id) &&  //i和i+1是同一辆车
            !strcmp(all[i].status, "in")    &&  //i的记录为 in
            !strcmp(all[i+1].status, "out") )   //i+1的记录为 out
        {
            valid[num++]=all[i];                //i和i+1是配对的,将两个记录都存入valid[]
            valid[num++]=all[i+1];

            //划重点(1): map<string, int> parkTime;
            int inTime = all[i+1].time-all[i].time;         //记录此次停留时间
            if( parkTime.count(all[i].id) == 0 ){           //map中还没有这个车牌号,置零
                parkTime[all[i].id] = 0;
            }
            parkTime[all[i].id] += inTime;                  //增加该车牌号的总停留时间
            maxTime = max(maxTime, parkTime[all[i].id]);    //更新最大总停留时间
        }
    }
    //步骤(3): 把有效记录按时间从小到大排序
    sort(valid, valid+num, cmp_byTime);

    //步骤(4): 输出该查询时刻校园内的车辆数
    //now 指向不超过当前查询时间的记录, numCar 为当前校园内车辆数
    int now=0, numCar=0;
    for(int i=0; i<k; i++){
        scanf("%d:%d:%d", &hh, &mm, &ss);
        int time=timeToInt(hh, mm, ss);
        //让now处理至当前当前查询时间
        while(now<num && valid[now].time<=time){
            if( !strcmp(valid[now].status, "in") )  numCar++;   //车辆进入
            else    numCar--;       //车辆离开
            now++;                  //now 指向下一条记录
        }
        printf("%d\n", numCar);     //输出该时刻校园内的车辆数
    }

    //步骤(5): //输出所有最长总停留时间的车牌号
    //遍历所有车牌号
    map<string, int>::iterator it;
    for(it = parkTime.begin(); it != parkTime.end(); it++){
        if(it->second == maxTime){  //输出所有最长总停留时间的车牌号
            printf("%s ", it->first.c_str());
        }
    }
    //输出最长总停留时间
    printf("%02d:%02d:%02d\n", maxTime/3600, maxTime%3600/60, maxTime%60);
    return 0;
}

 

PAT(A) 1016. Phone Bills (25)