PAT甲级-1016 Phone Bills

题目

 

题目大意

顾客打长途电话计费,输出每月的账单。输入一行给出一天24小时的计费钱数,注意单位是美分,还要乘以0.01。接下来给出n条记录,每条记录都包括客户名,时间,状态。“on-line”是开始打电话的时间,“off-line”是挂电话的时间。以乱序给出,还需要排序,时间是月:天:时:分,还有无效的通话记录,需要排除。如果一个用户没有有效的通话记录,则不输出这个用户。

要求按字母序输出人名,月份,以及每次通话的时间,和通话总额。

代码

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

struct message{
    string name;
    int d;
    int h;
    int m;
    string status;
};  // 结构体中的时间也拆分为天、时、分,更容易计算

bool cmp(message mes1, message mes2){
    if (mes1.name == mes2.name){
        if (mes1.d == mes2.d){
            if (mes1.h == mes2.h){
                return mes1.m < mes2.m;
            }else{
                return mes1.h < mes2.h;
            }
        }else{
            return mes1.d < mes2.d;
        }
    }else{
        return mes1.name < mes2.name;  // 字母序
    }
}

int main(){
    vector<double> m(24);
    double daym = 0;  // 一天的话费
    for (int i = 0; i < 24; i++){
        cin >> m[i];
        m[i] *= 0.01;
        daym += m[i] * 60;
    }
    int n, month;
    cin >> n;
    vector<message> mes(n);
    for (int i = 0; i < n; i++){
        cin >> mes[i].name;
        scanf("%2d:%2d:%2d:%2d", &month, &mes[i].d, &mes[i].h, &mes[i].m);  // 用scanf实现格式化读取
        cin >> mes[i].status;
    }
    sort(mes.begin(), mes.end(), cmp);

    message last;  // 每个用户的上一次通话记录
    int flag = 0;  // 用户有没有被输出过
    double sum = 0;  // 每个用户通话的总费用
    for (int i = 0; i < n; i++){
        if (i == 0){
            last.name = mes[i].name;
            last.d = mes[i].d;
            last.h = mes[i].h;
            last.m = mes[i].m;
            last.status = mes[i].status;
            continue;
        }
        if (mes[i].name != last.name){  // 下一个用户
            if (flag == 1){
                printf("Total amount: $%.2lf\n", sum);
                sum = 0;
            }
            flag = 0;
        }else{
            if (last.status == "on-line" && mes[i].status == "off-line"){  // 只有这种情况才合法
                int t = mes[i].d-last.d;
                int t1 = t * 24 * 60;
                int t2 = (mes[i].h - last.h) * 60;
                int t3 = (mes[i].m - last.m);
                double money = 0;  // 单次通话的费用
                money += t * daym;
                if(mes[i].h > last.h){
                    for(int j = last.h; j < mes[i].h; j++){
                        money += m[j] * 60;
                    }
                }else{
                    for(int j = mes[i].h; j < last.h; j++){
                        money -= m[j] * 60;
                    }
                }
                money -= last.m * m[last.h];  // 多的秒数减去
                money += mes[i].m * m[mes[i].h];  // 少的秒数加上
                if (flag == 0){
                    cout << mes[i].name << " ";
                    printf("%02d\n", month);
                    flag = 1;
                }
                printf("%02d:%02d:%02d %02d:%02d:%02d ", last.d, last.h, last.m, mes[i].d, mes[i].h, mes[i].m);  // 保证宽度为2且有前导0
                printf("%d $%.2lf\n", t1 + t2 + t3, money);
                sum += money;
            }
        }
        last.name = mes[i].name;
        last.d = mes[i].d;
        last.h = mes[i].h;
        last.m = mes[i].m;
        last.status = mes[i].status;  // 更新last
    }
    if (flag == 1){
        printf("Total amount: $%.2lf\n", sum);
    }  // 输出最后一个用户的Total amount

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值