1016 Phone Bills (25 分)思路、 难点分析、用例易错点

本文详细介绍了一种长话费计算系统的实现方案,包括数据存储结构设计、不合理通话记录的剔除逻辑及通话时间和费用的精确计算方法。通过案例演示,展示了如何处理不同情况下的通话费用计算,如同一天、跨天及跨多天的通话。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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-linerecord. 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

第一个难点:数据的存储,因为很明显通话时间是需要排序的,我们如果使用vector<node> node时一个结构体存储每一个通话开始时间或者结束时间,必定要使用sort(vector.begin(),vector,cmp);,但是姓名很明显也需要一个sort排序,那么只需要名字对应一个通话结构体的数组就行了,

struct node  //窗口
{
    int month;
    int day;
    int hour;
    int minute;
    int on;
};
struct person  
{
    string name;
    vector<node> vec;

};

 unordered_map<string,person> mapp; 便可实现了名字 对应person结构体,person结构体里面有node的数组,用来存放通话记录。

第二个难点:通话结构体node中会有一些没用的记录或者说是不合理的记录,我们便需要对每一个顾客在对应的vecotr数组中剔除不合理的记录,我们只保留  时间上从小到大,接听,挂断相邻的记录。这里用到了vector的erase方法,这个方法返回下一个迭代元素。

第三个难点,时间和费用的计算。我们首先把数据分为三类:第一类接通时间和挂断时间是同一天,第二类接通时间和挂断时间是相邻的两天,第三类接通时间和挂断时间相隔超过1天(比如1号通话到3号),对于第三类和第二类有个共同点,第三类中间肯定有完整的几天,完整的天数很简单的计算了吧,除去完整的这几天后剩下的时间就等于第二类了,只要计算相邻两天的通话费用。 那么相邻两天的通话费用怎么算,我们把两天分开计算,第一天计算到第一天的23时60分,第二天从00:00计算到第二天通话结束。那么此时你就会发现“第一天计算到这一天的23时60分”和“第二天从00:00计算到第二天通话结” 和第一类一样一样的,都是在同一天内计算两个时间的费用。下面我们讨论如何计算同一天 内的费用。我的代码如下,cost是存储0-23每个小时对应的多少钱一分钟. 整体思路就是从开始的通话小时 到结束通话的小时 一个for循环结束。但是但是但是一定要注意如果在同一个小时的情况,需要结束分钟减去开始分钟就行了,break就OK了,这里也是用例会考査的点

 

shour就是开始通话的小时 ehour就是结束通话的小时

int getTotal(int shour,int ehour,int sminute,int eminute,int cost[])
{
    int total=0;
    for(int i=shour; i<=ehour; i++)
    {
        if(shour==ehour)
        {
            total=(eminute-sminute)*cost[ehour];;
            break;
        }

        if(i==shour)
        {
            total+=(60-sminute)*cost[shour];
        }
        else if(i==ehour)
        {
            total+=eminute*cost[ehour];
        }
        else
        {
            total+=60*cost[i];
        }
    }
    return total;
}

AC的代码如下,不是很简洁,大家看看上面三点我感觉就能自己码出来了。

#include <iostream>
#include <cstdio>
#include <string.h>
#include <vector>
#include <algorithm>
#include <cmath>
#include <queue>
#include <sstream>
#include <unordered_map>
#include <set>
#include <climits>
#include <queue>
#include <hash_map>
#include <unordered_map>
using namespace std;

struct node  //窗口
{
    int month;
    int day;
    int hour;
    int minute;
    int on;
};
struct person  //窗口
{
    string name;
    vector<node> vec;

};
int cmp(node a,node b)
{

    if(a.day!=b.day)
        return a.day<b.day;
    else if(a.hour!=b.hour)
        return a.hour<b.hour;
    else
        return a.minute<b.minute;
}
int cmp2(string a,string  b)
{
    return a<b;
}
int getTotal(int shour,int ehour,int sminute,int eminute,int cost[])
{
    int total=0;
    for(int i=shour; i<=ehour; i++)
    {
        if(shour==ehour)
        {
            total=(eminute-sminute)*cost[ehour];;
            break;
        }

        if(i==shour)
        {
            total+=(60-sminute)*cost[shour];
        }
        else if(i==ehour)
        {
            total+=eminute*cost[ehour];
        }
        else
        {
            total+=60*cost[i];
        }
    }
    return total;
}

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

    unordered_map<string,person> mapp;
    vector<string> name_list;
    for(int i=0; i<yongli; i++)
    {
        string name;
        cin>>name;
        int month;
        int day;
        int hour;
        int minute;
        int on;
        scanf("%d:%d:%d:%d",&month,&day,&hour,&minute);
        string zhuangtai;
        cin>>zhuangtai;
        if(zhuangtai[1]=='n')
            on=1;
        else
            on=0;
        if(mapp[name].vec.size()==0)
            name_list.push_back(name);
        node node= {month,day,hour,minute,on};
        mapp[name].vec.push_back(node);
        mapp[name].name=name;

    }
    //姓名排序

    sort(name_list.begin(),name_list.end(),cmp2);

    unordered_map<string,person>::iterator it=mapp.begin();
    //sort(it->second.vec.begin(),it->second.vec.end(),cmp);
    for(int pp=0; pp<name_list.size(); pp++)
    {


        sort(mapp[name_list[pp]].vec.begin(),mapp[name_list[pp]].vec.end(),cmp);

//        for(int i=0;i<mapp[name_list[pp]].vec.size();i++){
//              // it->second.vec[i].on==1
//            printf("%02d:%02d:%02d\n",mapp[name_list[pp]].vec[i].day,mapp[name_list[pp]].vec[i].hour,mapp[name_list[pp]].vec[i].minute);
//
//        }
//        cout<<"一个结束"<<endl;
        //分类好了,下一步//剔除不合理的接电话 和挂电话记录
        int online=0;

        vector<node>::iterator diedai=mapp[name_list[pp]].vec.begin();
        for(; diedai!=mapp[name_list[pp]].vec.end();)
        {
            if(diedai->on==0)
            {
                if(online==0)
                {
                    diedai=mapp[name_list[pp]].vec.erase(diedai);

                }

                else
                {
                    online=0;
                    diedai++;
                    continue;
                }
            }
            else
            {
                if(online==1)
                {
                    diedai=mapp[name_list[pp]].vec.erase(diedai-1)+1;

                }
                else
                {
                    diedai++;
                    online=1;
                }
            }
        }
        if(online==1)
            mapp[name_list[pp]].vec.erase(mapp[name_list[pp]].vec.end()-1);

//计算时间和消费了
        if(mapp[name_list[pp]].vec.size()==0)
        {
            continue;
        }
        cout<<name_list[pp];
        printf(" %02d\n",mapp[name_list[pp]].vec[0].month);

        int sum=0;

        for(int q=0; q<mapp[name_list[pp]].vec.size(); q+=2)
        {
            int total=0;
            int fenzhongsum=0;
            int sday=mapp[name_list[pp]].vec[q].day;
            int shour=mapp[name_list[pp]].vec[q].hour;
            int sminute=mapp[name_list[pp]].vec[q].minute;

            int eday=mapp[name_list[pp]].vec[q+1].day;
            int ehour=mapp[name_list[pp]].vec[q+1].hour;
            int eminute=mapp[name_list[pp]].vec[q+1].minute;
            if(sday==eday)
            {
                total+=getTotal(shour,ehour,sminute,eminute,cost);
                fenzhongsum+=(ehour-shour)*60+eminute-sminute;
            }
            else if(sday+1==eday)
            {
                total+=getTotal(shour,23,sminute,60,cost);
                total+=getTotal(0,ehour,0,eminute,cost);

                fenzhongsum+=(24-shour)*60+0-sminute;
                fenzhongsum+=(ehour-0)*60+eminute-0;
            }
            else
            {
                total+=getTotal(shour,24,sminute,0,cost);
                total+=getTotal(0,ehour,0,eminute,cost);
                int daycost=0;
                for(int i=0; i<24; i++)
                {
                    daycost+=60*cost[i];
                }
                total+=daycost*(eday-sday-1);

                fenzhongsum+=(24-shour)*60+0-sminute;
                fenzhongsum+=(ehour-0)*60+eminute-0;
                fenzhongsum+=24*60*(eday-sday-1);
            }
            printf("%02d:%02d:%02d",mapp[name_list[pp]].vec[q].day,mapp[name_list[pp]].vec[q].hour,mapp[name_list[pp]].vec[q].minute);
            printf(" %02d:%02d:%02d",mapp[name_list[pp]].vec[q+1].day,mapp[name_list[pp]].vec[q+1].hour,mapp[name_list[pp]].vec[q+1].minute);
            printf(" %d $%.2f\n",fenzhongsum,(float)total/100);
            sum+=total;
        }
        printf("Total amount: $%.2f\n",(float)sum/100);
//输出顾客 和 合理的通话时间 并且排好序了
//        cout<<it->first;
//        printf(" %02d\n",it->second.vec[0].month);
//        for(int i=0;i<it->second.vec.size();i+=2){
//              // it->second.vec[i].on==1
//            printf("%02d:%02d:%02d",it->second.vec[i].day,it->second.vec[i].hour,it->second.vec[i].minute);
//            printf(" %02d:%02d:%02d\n",it->second.vec[i+1].day,it->second.vec[i+1].hour,it->second.vec[i+1].minute);
//
//        }
//        printf("Total amount: $%d\n",total);


    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值