PAT甲级-1016 Phone Bills (25分)

点击链接PAT甲级-AC全解汇总

题目:
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 wordon-lineor 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

题意:
计算每个人电话(网络?)的花费。
先输入0-23时间段的每分钟花费,单位是分。
然后输入不同人上线或下线的时间。

注意: 不是最开始上线到下一次下线的时间,而是最接近进下线的上线时间作为时间段。如例子中的aaa。

注意: 如果总cost是0的话,这个人的就不输出,不然case1 2会报错,所以把名字和月份都当参数传进去,只当有账单的时候才输出。

思路:
分三个部分:
第一部分计算从00:00到上线的时间和花费,这是-值;
第二部分计算隔了多少天,加完整一天的时间和花费;
第三部分计算00:00到下线的时间和花费,这是+值;
这样就可以不用担心跨天和不跨天的问题了!

我看到很多人是把所有时间和人都放到一起,先按照人排序,再按照时间排序,这样也可以,就省去了判断一个人是不是0 cost的情况。我是把每个人的时间放到每个人自己的上下线记录中,其实也差不多,多了判断是否为0的情况。

我的代码:

#include<bits/stdc++.h>
using namespace std;

int cost[24]={0};
int cost_one_day=0;

class Time{
public:
    Time(int a,int b,int c,int d,string line):
        mmonth(a),dday(b),hhour(c),mmin(d),on_or_off(line){}
    int mmonth,dday,hhour,mmin;
    string on_or_off;
};

bool cmp_time(Time a,Time b){
    if(a.dday!=b.dday)return a.dday<b.dday;
    else if(a.hhour!=b.hhour)return a.hhour<b.hhour;
    else return a.mmin<b.mmin;
}

class Person{
public:
    string name;
    vector<Time>his_time;
};

bool cmp_person(Person a,Person b){
    return a.name<b.name;
}

//输出两个时间,分钟,花费,再返回花费
int print_pair_time(Time online,Time offline){
    printf("%02d:%02d:%02d %02d:%02d:%02d ",online.dday,online.hhour,online.mmin,
                                            offline.dday,offline.hhour,offline.mmin);
    long long sum_min=0;
    int sum_cost=0;
    //减去00:00到online的时间和花费
    if(online.mmin>0)
    {
        sum_min-=online.mmin;
        sum_cost-=cost[online.hhour]*online.mmin;
    }
    while(online.hhour>0)
    {
        sum_min-=60;
        sum_cost-=cost[online.hhour-1]*60;
        online.hhour--;
    }
    //如果隔天了计算天数*每天的花费,没隔天+0
    sum_min+=60*24*(offline.dday-online.dday);
    sum_cost+=cost_one_day*(offline.dday-online.dday);
    //加上00:00到online的时间和花费
    if(offline.mmin>0)
    {
        sum_min+=offline.mmin;
        sum_cost+=cost[offline.hhour]*offline.mmin;
    }
    while(offline.hhour>0)
    {
        sum_min+=60;
        sum_cost+=cost[offline.hhour-1]*60;
        offline.hhour--;
    }
    printf("%lld $%.02f\n",sum_min,sum_cost/100.0);
    return sum_cost;
}

void print_times(string name,int month,vector<Time>times)
{
    int sum_cents=0;
    bool flag=true;
    for(int i=0;i<times.size()-1;i++)
    {
        if(times[i].on_or_off=="on-line"&&
           times[i+1].on_or_off=="off-line")
        {
            if(flag)
            {
                cout<<name;
                printf(" %02d\n",month);
                flag=false;
            }
            sum_cents+=print_pair_time(times[i],times[i+1]);
            i++;
        }
    }
    if(sum_cents>0)printf("Total amount: $%.02f\n",sum_cents/100.0);
}

int main()
{
    for(int i=0;i<24;i++)
    {
        cin>>cost[i];
        cost_one_day+=60*cost[i];
    }

    map<string,int>name_index;
    vector<Person>all_person;
    int N,index=1;
    cin>>N;
    for(int i=0;i<N;i++)
    {
        //输入这个人的名字,时间,上下线
        string name,line;
        cin>>name;
        int month,dd,hh,mm;
        scanf("%d:%d:%d:%d",&month,&dd,&hh,&mm);
        cin>>line;
        Time t_time(month,dd,hh,mm,line);

        if(name_index[name]==0)//没有这个人的记录则新建
        {
            Person t_person;
            t_person.name=name;
            t_person.his_time.push_back(t_time);
            all_person.push_back(t_person);
            name_index[name]=index++;
        }
        else//如果有这个人的话,把这个时间插入这个人的时间vector
        {
            all_person[name_index[name]-1].his_time.push_back(t_time);
        }
    }
    //人名升序排序
    sort(all_person.begin(),all_person.end(),cmp_person);
    //输出结果
    for(int i=0;i<all_person.size();i++)
    {
        sort(all_person[i].his_time.begin(),all_person[i].his_time.end(),cmp_time);
        print_times(all_person[i].name,all_person[i].his_time[0].mmonth,all_person[i].his_time);
    }

    return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值