4.8 PAT 甲级 1016 Phone Bills(超超超超麻烦的字符串题目)

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<iostream>
#include<map>
#include<vector>
#include<algorithm>
using namespace std;
const int M=24*60*31+10;
struct users
{
    int minutes;
    string state;
    string format_time;

    bool operator<(const users& t)const
    {
        return minutes<t.minutes;
    }
};
int main()
{

    //首先计算好从00:00到后面的每一分钟所需要的电话费
    int cost[25];
    for(int i=0;i<24;i++)
        cin>>cost[i];
    double sum[M];
    for(int i=1;i<M;i++)
        sum[i]=sum[i-1]+cost[(i-1)%1440/60]/100.0;

    //向map中写入用户通话数据
    int n;
    cin>>n;
    map<string,vector<users>>persons;
    char name[25],format_time[15],state[10];
    int money,month,day,hour,minute;
    for(int i=0;i<n;i++)
    {
        scanf("%s %d:%d:%d:%d %s",name,&month,&day,&hour,&minute,state);
        sprintf(format_time,"%02d:%02d:%02d",day,hour,minute);
        int minutes=(day-1)*1440+hour*60+minute;
        persons[name].push_back({minutes,state,format_time});
    }
    //分别计算每一个人的通话时间,电话费并输出
    for(auto person:persons)
    {
        auto name=person.first;
        auto info=person.second;
        sort(info.begin(),info.end());

        double total=0;
        for(int i=0;i+1<info.size();i++)
        {
            auto a=info[i],b=info[i+1];
            if(a.state=="on-line"&&b.state=="off-line")
            {
                if(!total)
                    printf("%s %02d\n",name.c_str(),month);
                cout<<a.format_time<<' '<<b.format_time<<' '<<b.minutes-a.minutes<<' ';
                double m=sum[b.minutes]-sum[a.minutes];
                printf("$%.2f\n",m);
                total+=m;
            }
        }
        if(total)
            printf("Total amount: $%.2f\n",total);
    }
    return 0;
}

哇 一题用生命在麻烦的题目= =。要是我不听y总的课。自己一个人琢磨一天都琢磨不出来。

题意是计算每个人的电话账单,然后按照用户名字的字典序输出用户的名字以及需要输出的一些信息。

输入:第一行是24个数字,分别代表0:00-01:00,01:00-02:00以此类推的每分钟的电话费,单位是美分。

           第二行是数字n,代表下面输入的行数。

           后面的n行分别输入 用户的姓名 + 4个用冒号相分隔的数字(第一个数字代表月份,第二个数字代表日期,第三个数字代表小时,第四个数字代表分钟)+字符串(on-line用我的理解就是接电话,或者打过去电话,off-line就是挂电话)。

输出:每一个用户为(2+打电话次数)行。

           第一行是用户名+月份(月份题意里说是每个人都在同一个月)。

           中间几行是按照时间排序的每一行是接电话(或者是打过去电话)的时间+挂电话的时间+整个电话持续的时间+这个电话需要付的电话费。

           最后一行是用户总共需要付的电话费。

规则是一个on-line 对应一个off-line。而且按照时间排序是上一个on-line必须对应下一个off-line,如果on-line没有对应的off-line或者off-line没有对应的on-line都可以忽视,如果一个人没有有效的通话记录这个人也可以忽视。

步骤:

①y总之前上课的时候说,如果分开去计算每一次通话的电话费,时间复杂度很大,所以可以用打表,也就是用空间换时间,也就是先开辟一个数组sum[],计算好从第一天00:00开始到某个时刻所需的电话费。到时候计算一段时间的电话费的时候,只需要计算出这两个时刻分别到第一天00:00的分钟数,找出对应的数组中的值做差,就是这一段时间的电话费。比如1月1号08:00到1月1号10:00的电话费就是sum[(1<这里的1代表1号>-1)*1440<1440代表一天的分钟数>+10<10代表当天的小时数>*60+0]-sum[(1-1)*1440+8*60+0].

②开始输入n,以及n组数据。用map加结构体去存储这些数据。在这题之前没接触过这么复杂的结构= =vector都没用过,就知道是跟数组差不多,map有个好处就是插入的数据会直接按照第一个值的字典序排列,所以后面要按照名字的字典序输出的时候就非常省事了。

③输入完数据,就是对遍历每一个人,处理map中的第二个数据,也就是我们的结构体,结构体里存着格式化好的时间,某个时间点距离第一天00:00的分钟数,和这个时刻的状态。先按照分钟数从小到大排个序。然后再进行遍历,判断是否存在上个是on-line,下个是off-line的两组数据,如果是就输出格式化的两个时间,和两个数据的分钟数差,以及电话费,并将电话费存入这个人的总电话费中,该用户的最后一行再输出总的电话费。

 

真的很麻烦。。各种数据结构都一无所知的我基本是半残废的看y总视频跟代码打下来的,思路全是他的= =

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值