1016 Phone Bills (25分)

大兔子大兔子 提交于 2020-01-14 02:47:23

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:

or 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

分析

  1. 名字不同的人按名字的字典顺序排序,名字相同的人按输入时间排序。
  2. 由于所有数据都是同一个月,可以以每月一号为起点,把时间转化为分钟,直接比较分钟就能比较时间的大小。
  3. 计算费用,不同的时间段费用不完全相同,跨时间段计算费用比较麻烦,同样可以以每月一号为起点,计算从一号开始到当前的总费用,再相减就能得到费用差。

设计结构体

struct Record{
    string name;
    int month, day, hour, minute, time, state;
};

time就表示从一号开始的总时间,state表示在线/离线

排序采用c++ STLsort()函数
传入的比较函数如下:

bool cmp(Record a, Record b){
    return a.name != b.name ? a.name < b.name:a.time < b.time;
}

计算费用差
从每月开始到当前的总费用

double cal(Record &r){
    double total = toll[r.hour]*r.minute + r.day*60*toll[24];
    for(int i=0; i<r.hour; i++){
        total += toll[i]*60;
    }
    return total/100.0;
}

代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <map>
#include <vector>
using namespace std;

int toll[25] = {0};

struct Record{
    string name;
    int month, day, hour, minute, time, state;
};

bool cmp(Record a, Record b){
    return a.name != b.name ? a.name < b.name:a.time < b.time;
}

double cal(Record &r){
    double total = toll[r.hour]*r.minute + r.day*60*toll[24];
    for(int i=0; i<r.hour; i++){
        total += toll[i]*60;
    }
    return total/100.0;
}

int main(){
    int n;
    for(int i=0; i<24; i++){
        cin>>toll[i];
        toll[24] += toll[i];
    }
    cin>>n;
    vector<Record> record;
    for(int i=0; i<n; i++){
        Record r;
        cin>>r.name;
        scanf("%d:%d:%d:%d", &r.month, &r.day, &r.hour, &r.minute);
        string tmp;
        cin>>tmp;
        r.state = tmp == "on-line" ? 1:0;
        r.time = r.day*24*60 + r.hour*60 + r.minute;
        record.push_back(r);
    }
    sort(record.begin(), record.end(), cmp);
    map<string, vector<Record> > mp;
    for(int i=1; i<n; i++){
        if(record[i].name == record[i-1].name && record[i-1].state == 1 && record[i].state == 0){
            mp[record[i-1].name].push_back(record[i-1]);
            mp[record[i].name].push_back(record[i]);
        }
    }
    map<string, vector<Record> >::iterator it;
    for(it=mp.begin(); it!=mp.end(); it++){
        vector<Record> tmp = it->second;
        cout<<it->first;
        printf(" %02d\n", tmp[0].month);
        double total = 0;
        for(int i=0; i<tmp.size(); i+=2){
            double t=cal(tmp[i+1]) - cal(tmp[i]);
            printf("%02d:%02d:%02d %02d:%02d:%02d %d $%.2f\n", tmp[i].day, tmp[i].hour, tmp[i].minute, tmp[i+1].day, tmp[i+1].hour, tmp[i+1].minute, tmp[i+1].time-tmp[i].time, t);
            total += t;
        }
        printf("Total amount: $%.2f\n", total);
    }
    return 0;
}

代码中的toll[24]是个很巧妙的设计,采用vectormap,可以大大简化代码,可以查看其用法。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!