PAT_甲级_1016 Phone Bills

题目大意:

给出24h中每个小时区间内的资费(cents/minute),并给出N条通话记录,每条通话记录都记录了姓名、当前时刻(月:日:时:分)以及其属于通话开始(on-line) 或是通话结束(off-line)。现在需要对每个人的有效通话记录进行资费计算,有效通话记录是指同一个用户能够配对的所有on-line和off-line,而这样的配对需要满足:在按时间顺序排列后,两条配对的on-line和off-line对应时间内不允许出现其他的on-line或off-line的记录。输出要求:按姓名的字典序从小到大的顺序输出存在有效通话记录的用户。对单个用来说,需要输出他的姓名、账单月份(题目保证单个用户的所有记录都在同一个月产生)以及有效通话记录的时长和花费,最后输出他的总资费。

算法思路:

由于需要对每一个用户的账单进行输出,所以这里采用按照用户分组的方式来处理,由于输出也是需要按照字典序进行输出,所以这里先对所有的记录进行排序,对于名字不同的按照字典序排序,对于名字相同的记录按照每条记录的产生时间从前往后排序。然后处理每一组用户,使用2个指针work_pointer和next_person,分别表示当前用户的工作指针和下一个用户的第一条记录的位置。在work_pointer和next_person之间的就是同一个用户。那么在同一用户之间只需要找到一对,也就是紧紧挨着的2条记录,上一条为on-line,下一条为off-line,这样就找到了一条有效记录,有可能会出现没有有效记录的情况,这里使用一个标识ispaired
来记录是否有有效记录,在生成账单的时候设置为true,在当前用户遍历完毕的时候,如果ispaired为true,那么就保留当前人的账单。并且更新work_pointer为next_person,进入下一个用户的遍历。

时间的处理:
对于月份使用一个变量month就可以保存,然后对于天,小时和分全部转化为分钟来进行处理。
一条有效记录费用的计算:

这里给出2种方法,第一种就是采用加法,每加一分钟就累计当前小时的每一分钟的费用,然后直到开始时间和结束时间相等。代码就是如下的
callOneRecordCharge函数:

// 计算一条记录的收费
double callOneRecordCharge(int start_time,int end_time){
    int sdd = start_time/24/60;
    int shh = start_time%(24*60)/60;
    int smm = start_time%(24*60)%60;
    double sum = 0;
    while (start_time

第二种方法采用减法,先计算从00:00:00到开始时间的花费,然后计算从00:00:00到结束时间的花费,然后让后者减去前者得到开始时间到结束时间的花费,代码如下:

double cal(int time){//计算00:00:00到time的花费
    int dd = time/(24*60);//天
    int hh = time%(24*60)/60;//小时
    int mm = time%60;//分钟
    double charge = 0;//00:00:00到time时间的花费
    for(int i=0;i

这里采用了第一种方法

注意点:

1、资费的输出需要进行单位换算,即把cent换算为dollar,所以结果要除以100。
2、同一用户的通话记录按照时间先后进排序输出。这里使用了map就是会自动排序
3、测试点1,2,3都是在判断是否会输出无效记录,这里给出一组数据供参考,如果输出了3个用户就是错的。

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 on-line
CYJJ 01:01:07:00 off-line
CYLL 01:01:08:03 on-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 on-line

4、输出格式中一般整型都得是%02d的格式,但是单条记录的花费直接用%d,总花费得用%.2f
5、work_pointer

提交结果:

PAT_甲级_1016 Phone Bills_第1张图片

AC代码:
#include
#include
#include
#include
#include
#include 

using namespace std;

int rate[24];// 每小时区间的每分钟收费率
int month;// 月份

struct Record{
    string name;// 顾客的名字
    int time; // 该记录产生的时间
    bool isOnline; // 是否是on-line记录
};

struct Bill{
    string name;// 顾客的名字
    map pair_time;// 所有通话记录,key为起始时间,value为结束时间
};

// 将时间转化为分钟
int getMinutes(int dd,int hh,int mm){
    return dd*24*60+hh*60+mm;
}

// 计算一条记录的收费
double callOneRecordCharge(int start_time,int end_time){
    int sdd = start_time/24/60;
    int shh = start_time%(24*60)/60;
    int smm = start_time%(24*60)%60;
    double sum = 0;
    while (start_time::iterator iter;
    double total_amount = 0;
    for (iter=bill.pair_time.begin();iter!=bill.pair_time.end();++iter){
        int start_time = iter->first; // 拨通电话时间
        int end_time = iter->second; // 挂断电话时间
        int sdd = start_time/24/60;
        int shh = start_time%(24*60)/60;
        int smm = start_time%(24*60)%60;
        int edd = end_time/24/60;
        int ehh = end_time%(24*60)/60;
        int emm = end_time%(24*60)%60;
        double amount = callOneRecordCharge(start_time,end_time);
        total_amount += amount;
        printf("%02d:%02d:%02d %02d:%02d:%02d %d $%.2lf\n",sdd,shh,smm,edd,ehh,emm,end_time-start_time,amount);
    }
    printf("Total amount: $%.2lf\n",total_amount);
}

int main(){
    for (int i = 0; i < 24; ++i) {
        scanf("%d",&rate[i]);
    }
    int N;//记录条数
    scanf("%d",&N);
    char name[30];
    int dd,hh,mm;
    char line[10];
    vector records;
    for (int j = 0; j < N; ++j) {
        Record record;
        scanf("%s %d:%d:%d:%d %s",name,&month,&dd,&hh,&mm,line);
        record.name = name;
        record.isOnline = strcmp(line,"on-line")==0;
        record.time = getMinutes(dd,hh,mm);
        records.push_back(record);
    }
    // 排序
    sort(records.begin(),records.end(),cmp);
    // 生成所有人的账单
    int work_pointer = 0;// 工作指针,初始指向每个人记录的第一个,之后指向第一个为on-line的记录
    int next_person = 0; // 记录下一个人的初始记录的位置
    vector bills;// 所有人的账单
    while (work_pointer

你可能感兴趣的:(算法-数据结构,c++)