pat 甲级测试题目 -- 1016 Phone Bills

题目链接

题目描述

要求计算银行账单。
输入
第一行给你一天24小时(00:00~01:00 ...)每个小时每分钟的话费,单位是美分
第二行给你顾客列表(N 个)
接下来的 N 行是顾客的账单详情
CYLL 01:01:06:01 on-line
姓名 月:日:小时:分钟 状态
CYLL 01:28:16:05 off-line
姓名 月:日:小时:分钟 状态
on-line 和 off-line 必须一一对应该记录才有效

输出
对于输入有效的顾客,给出该顾客这个月的账单,格式如下
CYJJ 01
姓名 月份
01:05:59 01:07:00 61 $12.10
通话开始时间 通话结束时间 话费
Total amount: $12.10
这个月的总额话费

注意:
每次的输入,顾客的月份都是一样的。
测试用例中会出现跨天的情况。

分析

看到这道题目之后,我考虑过单纯的使用 map 或者结构体存储数据,最后确定用 map<string, vector>,也就是map + vector + 结构体 的方式存储。尽管成功的存储了,但是到了处理数据这里,对于姓名排序以及时间排序的处理让我着实头痛。无奈就去参考了网上的代码。参考网址
不得不说柳神真的是名不虚传。不仅用总计日时分的时间解决了时间上的排序问题,而且用总计日时分的话费解决了跨天的话费计算问题,这两个方法都有共性吧。。。学习到了!我参考(抄袭←_←)柳神的代码后,将其思路列在代码注释里面了

实现

#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
#include <string>

using namespace std;

struct node {
    string name;
    int month, day, hour, minute, statue, time; // 定义 time 用于比较时间
};

bool cmp(node a, node b) {
    return a.name == b.name ? a.time < b.time : a.name < b.name; // 按照姓名比较,姓名相同按照时间比较,方便计算费用
}
// 计算总时间的话费,用于解决跨天问题
double CallSpend(node cus, int* rate){
    double total = rate[cus.hour] * cus.minute + cus.day * rate[24] * 60;
    for (int i = 0; i < cus.hour; ++i) {
        total += rate[i] * 60;
    }
    return total/100;
}

int main() {
    int rate[25] = {0}, n;
    // 接收计费数据
    for (int i = 0; i < 24; ++i) {
        cin >> rate[i];
        rate[24] += rate[i]; // 将一天的话费数据计算出来,用于解决跨天计算话费的问题
    }
    cin >> n;
    vector<node> custom(n);
    for (int i = 0; i < n; ++i) {
        cin >> custom[i].name;
        scanf("%d:%d:%d:%d", &custom[i].month, &custom[i].day, &custom[i].hour, &custom[i].minute);
        string stemp;
        cin >> stemp;
        custom[i].statue = ((stemp == "on-line") ? 1 : 0);
        custom[i].time = custom[i].day * 24 * 60 + custom[i].hour * 60 + custom[i].minute;
    }
    // 对顾客数据进行排序
    sort(custom.begin(), custom.end(), cmp);
    // 用 map 存储数据,将同一个顾客的月账单统一
    map<string, vector<node>> list;
    for (int i = 1; i < n; ++i) {
        if (custom[i].name == custom[i - 1].name && custom[i - 1].statue == 1 && custom[i].statue == 0) {
            list[custom[i - 1].name].push_back(custom[i - 1]);
            list[custom[i].name].push_back(custom[i]);
        }
    }
    // 遍历 map 输出账单
    for (auto li : list) {
        vector<node> temp = li.second;
        cout << li.first;
        printf(" %02d\n", temp.front().month);
        double total = 0;
        for (int i = 1; i < temp.size(); i+=2) {
            // 计算一次通话记录的话费
            double t = CallSpend(temp[i], rate) - CallSpend(temp[i-1], rate);
            printf("%02d:%02d:%02d %02d:%02d:%02d %d $%.2f\n", temp[i-1].day, temp[i-1].hour, temp[i-1].minute, temp[i].day, temp[i].hour, temp[i].minute, temp[i].time - temp[i-1].time, t);
            total += t;
        }
        printf("Total amount: $%.2f\n", total);
    }
    return 0;
}

希望能帮到大家

原文地址:https://www.cnblogs.com/Breathmint/p/10346631.html

时间: 2024-10-10 13:05:55

pat 甲级测试题目 -- 1016 Phone Bills的相关文章

PAT 甲级测试题目 -- 1009 Product of Polynomials

题目链接 这题占个坑吧...我用了两种思路,一种将保存结果的数组初始化为 0,把乘积加上去,顺便记录下最后一个指数的值.用两次 2000 次 for 循环过滤掉 0 值以及输出答案,这个代码过了,但是后期测试的时候,有些测试用例会多出来空格,有些则格式不对..但是过了... 代码如下 #include<iostream> #include<stdio.h> using namespace std; int main() { double A[1001], B[1001]; int

PAT 甲级测试题目 -- 1010 Radix

题目链接 题目描述 给你两个数以及其中一个数的基数(进制数),找出另一个数的基数,找不到就输出 Impassible 分析 思路不是很难,基本可以用进制转换加循环判断做,但是有坑... 坑1:上界不是36....上界是确定的那个数的十进制加 1 . 坑2:暴力循环会导致时间超限,用二分法解决 坑3:二分过程中会有数据溢出,得到的负数处理方式和找到较大数处理方式一样,因为溢出的数和题目条件不符,所以可以舍弃. 实现 #include<iostream> #include<string.h&

PAT 甲级测试题目 -- 1012 The Best Rank

题目链接 题目描述 输入小于等于 2000 的数据 N,M,分别表示 学生的总数 和 查询学生的数量 输入 N 个学生的六位数 id 以及 C,M,E 三科成绩.输入 M 个查询学生的 id. 要求输出: 若被查询的 id 不存在,输出 N/A 若被查询的 id 存在,输出 C,M,E,A(average 平均分) 四个成绩中排名最高的排名,以及对应的分数类型(C, M, E, A).若有多余一个类型的分数相同,则按照 A > C > M > E 的优先序列输出 排名 和 分数类型 分析

PAT 甲级测试题目 -- 1013 Battle Over Cities

题目链接 题目描述 ??给你城市的数量 N(N<1000),城市中地铁的数量 M 以及 被可能占领的城市数量 K(每一次只占领一个城市,并且每次占领的城市不一样),接下来的 M 行根据地铁的数量给出每个地铁连接的两个城市编号.最后一行给你被占领的城市序列.城市编号为 1 到 N,请你求出若某个城市被占领了,连通剩下城市所需要修建的地铁个数. 分析 ??该题考察图的存储以及遍历.本题的难点在于把 "需要维修多少个地铁" 这个问题转换成 "需要多少次 dfs 才能遍历完整个

PAT甲题题解-1016. Phone Bills (25)-模拟、排序

博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/6789229.html特别不喜欢那些随便转载别人的原创文章又不给出链接的所以不准偷偷复制博主的博客噢~~ 给出一天24小时内,每个小时内,每分钟的通话费用给出n个记录,on-line表示通话的开始,off-line表示通话的结束如果on-line/off-line没有对应的另一个,忽略即可 先按人名排序,名称一样的按时间排序,这里时间统一按分钟来算,即一天有24

PAT 甲级 1016 Phone Bills (25 分) (结构体排序,模拟题,巧妙算时间,坑点太多,debug了好久)

1016 Phone Bills (25 分)   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 connec

1016. Phone Bills (25)——PAT (Advanced Level) Practise

题目信息: 1016. Phone Bills (25) 时间限制 400 ms 内存限制 32000 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue A long-distance telephone company charges its customers by the following rules: Making a long-distance call costs a certain amount per minute, depending

PAT 1016. Phone Bills

PAT 1016. 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

pat甲级1016

1016 Phone Bills (25)(25 分) 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 conn