PAT-A1016-Phone Bills

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.

输入描述

 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.

输出描述

 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.


示例:

输入

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

输出

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


解题思路

  首先使用结构数组存储输入的记录(姓名,月份,日,时,分,以及对应的状态 on-line || off-line),使用toll数组存储收费的标准。
 读取数据:读取24小时的收费标准,存储每条记录的数据,在结构体中我们定义的是on-line对应的状态是true,off-line对应的状态是false。
 首先开始对数据的排序,需要自定义函数cmp,在自定义函数中我们需要根据比较规则进行判断(小的编号开始、月份小的排序在前等等)。
 开始遍历数据,首先开始遍历数据,首先需要将判断同一个人的记录是否是有效的通话记录,我们只有on-line和off-line同时存在时候才是有效的数据,最后next存储指向的是下一个人的通话记录
 在遍历的有效数据之前我们需要将输出该人姓名和记录。
 开始遍历当前人的记录,有效记录一定是连续的,因此存在on和on+1的关系,找到我们需要的位置之后,先输出on和off对应的记录信息。
 根据两个数据的时间差计算该条记录的收费,累加到总和中。
 之后将on移动到off就开始遍历下一个的数据。

参考代码

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

//记录数据的结构数组
struct Record {
    char name[25];
    int month, dd, hh, mm;
    bool status;
} Record[1010], temp;

int toll[25] ;//收费标准

//根据规则定义的比较函数作为sort的最后一个参数
bool cmp(struct Record a, struct Record b) {
    int s = strcmp(a.name, b.name);//相等返回0,小于返回负数,大于返回正数
    if (s != 0) { return s < 0; }
    else if (a.month != b.month) { return a.month < b.month; }
    else if (a.dd != b.dd) { return a.dd < b.dd; }
    else if (a.hh != b.hh) { return a.hh < b.hh; }
    else { return a.mm < b.mm; }
}

void get_ans(int on, int off, int &time, int &money) {
    temp = Record[on]; //为了不改变原始数据,我们需要使用一个临时变量进行存储
    while (temp.dd < Record[off].dd || temp.hh < Record[off].hh || temp.mm < Record[off].mm) { //常用的计算时间差的步骤
        time++;
        money += toll[temp.hh];
        temp.mm++;
        if (temp.mm >= 60) {
            temp.hh++;
            temp.mm = 0;
        }
        if (temp.hh >= 24) {
            temp.dd++;
            temp.hh = 0;
        }
    }

}


int main() {
    for (int i = 0; i < 24; ++i) {
        scanf("%d", &toll[i]);
    }
    int n;
    char line[10];
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        scanf("%s", Record[i].name);
        scanf("%d:%d:%d:%d", &Record[i].month, &Record[i].dd, &Record[i].hh, &Record[i].mm);
        scanf("%s", line);
        if (strcmp(line, "on-line") == 0) { //根据字符串的比较判断 该条数据是数据on-line哈市off-line
            Record[i].status = true;
        } else {
            Record[i].status = false;
        }
    }
    sort(Record, Record + n, cmp); //排序 
    int on = 0, off, next; //三个变量的意思是 on-开始数据的位置,off-同一个人数据结束的位置,next下一个人数据开始的位置
    while (on < n) { //从0开始遍历数据
        int needPrint = 0;
        next = on; 
        while (next < n && strcmp(Record[on].name, Record[next].name) == 0) { //判断一个人数通话记录数据是否有效 
            if (needPrint == 0 && Record[next].status == true) {
                needPrint = 1;
            } else if (needPrint == 1 && Record[next].status == false) {
                needPrint = 2;
            }
            next++;
        }
        if (needPrint < 2) {//非有效 就开始遍历下一个人的数据 这里有坐标位置的变动
            on = next;
            continue;
        }
        int Allmoney = 0;
        printf("%s %02d\n", Record[on].name, Record[on].month); 
        while (on < next) {
            while (on < next - 1 && !(Record[on].status == true && Record[on + 1].status == false)) { //判断当前个人的数据
                on++;
            }
            off = on + 1;
            if (off == next) {  //当当前的个人的数据遍历完的时候,退出本循环
                on = next;
                break;
            }
            printf("%02d:%02d:%02d ", Record[on].dd, Record[on].hh, Record[on].mm);
            printf("%02d:%02d:%02d ", Record[off].dd, Record[off].hh, Record[off].mm);
            int time = 0, money = 0;
            get_ans(on, off, time, money); //当前记录计算收费总和
            Allmoney += money;//累加到个人
            printf("%d $%.2f\n", time, money / 100.0);//单位的换算
            on = off + 1;
        }
        printf("Total amount: $%.2f\n", Allmoney / 100.0);//输出总和
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值