文章目录

  • 题目分析
  • 题目链接

题目分析

原题:

长途电话公司按以下规则向客户收费:

拨打长途电话每分钟要花费一定的费用,具体收费取决于拨打电话的时间。

客户开始拨打长途电话的时间将被记录,客户挂断电话的时间也将被记录。

每个月都要给客户发送一次话费账单,账单中应包含每次通话记录以及相关收费等信息。

给定一组电话记录,你的工作是为客户准备帐单。

输入格式
输入包含两部分:费率结构和电话记录。

费率结构由一行组成,该行包含24个非负整数,分别表示从 00:00-01:00 的收费(分/分钟),从 01:00-02:00 的收费,以此类推…

下一行包含一个正整数 N。

接下来 N 行,每行包含一条记录。

每个记录由客户名称(最多 20 个字符的字符串,不带空格),时间和日期(mm:dd:hh:mm)以及单词 on-line 或 off-line 组成。

所有日期都在同一个月内,每个 on-line 记录都与按时间顺序排列的同一位客户的下一条记录配对,但前提是这条记录是 off-line。

所有未与 off-line 记录配对的 on-line 记录以及未与 on-line 记录配对的 off-line 记录都必须忽略。

输入中至少包含一个成功的配对。

同一客户在同一时间不会有两个或以上的电话记录。

使用 24 小时制记录时间。

输出格式
你需要为每个客户打印电话费。

账单必须按照客户姓名的字母顺序(按ASCII码顺序,大写字母在前,小写字母在后)打印。

对于每个客户,首先以示例显示的格式在一行中打印客户名称和帐单月份。

然后,对于每个通话时间段,在一行中分别打印开始和结束时间和日期(dd:hh:mm),持续时间(以分钟为单位)和通话费用。

通话必须按时间顺序列出。

最后,以示例显示的格式打印该月的总费用。

注意,没有任何有效通话记录的客户直接忽略,不予打印账单。

数据范围
1≤N≤1000

题目分析:

特点:题干很长,需要花时间去阅读。

分析:这道题有点不会处理,在纠结用不用结构体。

  1. 很多信息使用结构体,然后使用map建立映射,本题map< 姓名, vector<结构体> > 。 这样保存联系,当然需要熟悉结构体排序sort,重载< 或者重写cmp函数。
  2. 后面字符串中 CYLL 01:01:06:01 on-line 月份、日期、小时、分钟用int数来存,不用字符串来存。
  3. 复杂读入、输出多用C语言!!!!

另外需要提到的一点是:读入数据是没有顺序的,可能off-line的在前,也可能on-line的在前。但是好在 同一个人打电话区域是不重叠的!!!什么意思呢?意思是 张三1月1号7:00开始打电话,打到1月1号7:15,这是一次完整的通话,数据中不会出现张三1月1号7:10又开始打电话(上一次数据是7:00 ~ 7:15,7:10开始打电话与之冲突)这种数据。

想到了这一点,就可以仅仅按照时间来排序,而不用在排序的时候还要考虑online还是offline。 因为 按时间排好之后一次完整的通话一定是在一起的,即上面的是online,下一个就是同一次通话的offline。没有在一起的就是非法数据。

学习很多C语言的优点

sprintf函数的作用:将一个格式化的字符串输入到另一个字符串中。sprintf()一般是三个参数:第一个是目的字符串,第二个是格式,比如“%02d”,第三个就是变量。

比如

char buf[30];
int day ,hour ,minute;  //假设已经赋过值
sprintf(buf , "%02d:%02d:%02d", day , hour , minute);  //意思是格式化为xx:xx:xx 这样的形式 xx不足两位的补零

sprintf()函数的用法总结

还有 .c_str()函数,

使用printf("%s")输出的时候需要 char * ,不能使用string类型, 需要函数 c_str()进行转换:把string转换为 char *

warning: format '%s' expects argument of type 'char*', but argument 2 has type 'std::string' {aka 'std::basic_string<char>'} [-Wformat=]

ac代码

学习别人的代码

#include<bits/stdc++.h>
using namespace std;const int N =1010,M=31*1440+10; // 每天1440分钟,每月最多31天。另外再多开10个大小
int cost[24];struct Record{int minutes;  //字符串时间转化为分钟数string state;string format_time;//按照时间从小到大排序, 重载 < 运算符bool operator< (const Record& t)const{return minutes < t.minutes;}
};//hash表映射
// 第一个是name ,后面是一个vector ,vector里面存了一个结构体。
//同名字的记录都push_back到 vector中作为一项。/*
差不多是这样的
张三对应一个vector: {一条记录(结构体),一条记录,一条记录,...}
李四对应一个vector:{一条记录(结构体),一条记录,一条记录,...}
*/
map<string,vector<Record>> persons;double sum[M];// 前缀和数组,用来求本月1号0点0分 到任何一天任何时间花费的钱数int n;int main(){for(int i=0;i<24;i++) cin >>cost[i];// 预处理 本月1号00:00分 到 本月 任意时间x号xx:xx分 打电话的花费//i 这里遍历的是一个月中的所有分钟  //   %1440 是看在几号(一天1440分钟) ;而/60是看在哪个小时时间段,用来看此时的电话费for(int i=0; i< M ;i++)  sum[i] =sum[i-1] + cost[ (i- 1) % 1440 / 60  ] /100.0;cin>>n;char name[25] ,state[10], format_time[20];int month ,day ,hour ,minute;for(int i=0;i<n;i++){scanf("%s %d:%d:%d:%d %s",name, &month, &day, &hour, &minute, state);sprintf(format_time ,"%02d:%02d:%02d", day ,hour ,minute);int minutes = (day -1) * 1440 +hour * 60 + minute; //记录距离该月1号00时00分的分钟数,方便前缀和求解persons[name].push_back({minutes, state, format_time}); //结构体压入姓名对应的vector} for(  const auto & p :persons ){auto name = p.first;auto  records =  p.second;  //是map里面的那个vectorsort(records.begin(),records.end());double total = 0;for(long unsigned i=0 ; i + 1 < records.size() ;i ++){ //每次遍历两条记录auto a = records[i] ,b = records[i+1];if(a.state == "on-line" && b.state =="off-line"){if(!total){printf("%s %02d\n",name.c_str(),month);  // 输出姓名和月份}cout<< a.format_time <<" "<<b.format_time<<" ";double charge = sum[b.minutes] -sum[a.minutes];printf("%d $%.2lf\n",b.minutes - a.minutes, charge);total+=charge;}}if(total) printf("Total amount: $%.2lf\n",total);}}

ac代码:
自己独立写的代码:vector自定义排序还是喜欢重写cmp函数,这里比较的是结构体。

#include<bits/stdc++.h>
using namespace std;const int N =1000 , M =24*60; //M一天多少分钟const int minutesOfAMonth= 31*M+10;struct Record{int  minute;  //存这个时间到初始之差string formatTime;  //格式化的信息string state; //状态 offline还是online};//结构体按照 时间排序
//因为vector里面存的是结构体,所以要对结构体进行操作。
bool cmp(Record a, Record b){return a.minute < b.minute;
}//姓名 和自己的记录 之间的map
map<string ,vector<Record>> records;int cost[30];//刚开始,sum前缀和类型写成int了,不要犯这种小错误。
double sum[minutesOfAMonth];int main(){int n;for(int i=0;i<24;i++) cin>>cost[i];for(int i=1;i<minutesOfAMonth;i++) sum[i] = sum[i-1] + cost[ (i-1) %M  / 60 ]/100.0;cin>>n;char name[25] ,state[10],formatTime[20];int month ,day ,hour, minute;//信息全部读入在records中for(int i=0;i<n;i ++){scanf("%s %02d:%02d:%02d:%02d %s", name ,&month ,&day ,&hour, &minute, state);int minutes = (day-1)*M + hour*60 + minute;sprintf(formatTime,"%02d:%02d:%02d",day, hour ,minute );//cout<<formatTime <<endl;records[name].push_back({minutes,formatTime ,state });}//处理records中的数据for(const auto & rec : records){double total =0;auto name = rec.first;auto person = rec.second;// person 是个vectorsort(person.begin(),person.end(),cmp);//每次遍历2个记录for( unsigned i =0;i+1 <person.size(); i++){  auto a = person[i], b = person[i+1];if(a.state=="on-line" && b.state== "off-line"){//每个人只输出一次姓名和月份,如果total==0 ,代表刚开始这个人,所以输出if(!total){printf("%s %02d\n", name.c_str() , month);  // C语言中string转化成char * 类:函数c_str()    }double charge = sum[b.minute] - sum[a.minute];printf("%s %s %d $%.2lf\n", a.formatTime.c_str(), b.formatTime.c_str(), b.minute - a.minute, charge );total += charge;}}//如果total不为0,代表这个人合法,则需要输出总费用if(total) printf("Total amount: $%.2lf\n",total);}}

题目链接

PAT甲级1016 Phone Bills

PAT甲级1016 Phone Bills :[C++题解]字符串处理(复杂题)(C语言格式化读入、输出很便利!!!)相关推荐

  1. PAT甲级1077 Kuchiguse:[C++题解]字符串、最长公共后缀

    文章目录 题目分析 题目链接 题目分析 来源:acwing 分析: 读入n个字符串s[n],以s[0]为基础找公共后缀.枚举后缀的长度,内层循环遍历其他字符串,判断是否后缀相等. 使用子串的函数sub ...

  2. PAT甲级1061 Dating:[C++题解]字符串处理(C语言格式控制牛逼!)

    文章目录 题目分析 题目链接 题目分析 题意重述:四个字符串,前两个字符串是一组:求 日期和小时: 后两个字符串是一组:求分钟. 对于前两个字符串: 需要统计两次,位置相同并且是相同的字符. 第一个符 ...

  3. PAT甲级1035 Password:[C++题解]字符串修改

    文章目录 题目分析 题目链接 题目分析 题目重述: 题目分析: 把需要更改的字母和对应的字母分别存在string中,两者下标索引要对应. 采用 vector来存储< string, string ...

  4. PAT甲级 1016 Phone Bills(时间差)

    Link 题意: 远程电话的收费是按照每分钟来计费的,现在告诉你一天24小时中每分钟的收费标准,以及n条通话记录,试求出每个人该月的消费账单. 只有开始记录没有结束记录的通话不计费,反之亦然.保证所有 ...

  5. PAT甲级题目翻译+答案 AcWing(字符串处理)

    1001 A+B Format (20 分) 题意 :将整数转换成标准格式 思路 :从后往前遍历字符串进行模拟,每三个数字加一个逗号,但不能是在最前面加逗号,也不能是加在负号后面 #include & ...

  6. PAT甲级1029 Median:[C++题解]贪心、二路归并

    文章目录 题目分析 题目来源 题目分析 来源:acwing 分析: 如果直接排序,时间复杂度是O(nlogn),n=2∗105O(nlogn),\ n=2*10^5O(nlogn), n=2∗105会 ...

  7. PAT甲级1070 Mooncake:[C++题解]贪心

    文章目录 题目分析 题目来源 题目分析 来源:acwing 分析: 对单件从高到低排序. 需要注意的是总需要量d设成double,不要设成int. ac代码 #include<bits/stdc ...

  8. PAT甲级1008 Elevator:[C++题解]模拟

    文章目录 题目分析 题目来源 题目分析 来源:acwing 分析:统计上升次数.下降次数:停留次数就是n.然后算数即可. ac代码 #include<bits/stdc++.h> usin ...

  9. PAT甲级1078 Hashing:[C++题解]哈希表、哈希表开放寻址法、二次探测法

    文章目录 题目分析 题目链接 题目分析 来源:acwing 分析: 本题建立hash表是利用只具有正增量的二次探测法来解决冲突, 索引 = 数 % 哈希表的大小 如果映射到同一个索引idx,hash表 ...

最新文章

  1. LVM逻辑卷的缩减与删除,LVM逻辑卷快照,btrfs文件系统,网络管理
  2. node-express-1
  3. C - Rencontre Gym - 102798C
  4. WMRouter:美团外卖Android开源路由框架
  5. maven报错:Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:x.x.x:test
  6. 怎么修改db2服务器名字,服务器创建db2数据库实例名
  7. c语言学习-有一12个元素的整型数组b,从键盘输入数据,请以每行4个数据各个数据之间空两格的形式输出b数组的12个元素
  8. rdt1.0,rdt2.0,rdt2.1,rdt2.2,rdt3.0
  9. 2021-08-01mysql外键
  10. 类似c语言sizeof,sizeof()与strlen()在C语言中有什么不同
  11. java编程简单网络_Java网络编程之使用Socket搭建一个简易聊天室
  12. 利用纯真ip库搭建ip查询服务
  13. linux ps 简书,Linux小白学习法宝-命令大全第一部分
  14. 规则引擎 Easy rule 使用总结
  15. 微信V3版本支付下单、查询支付订单状态、订单退款接入正式项目中并引入策略模式实操
  16. 各大厂800道Java后端经典面试题合集
  17. 华为设备无线环境中的MAC认证
  18. 手动删除7千万个Reids的Key是什么体验响!
  19. window10或XP 定时换壁纸,添加计划到windows任务里,cmd换壁纸
  20. java 136年以后的时间_136年后 圣家族大教堂终于获得了建筑许可证

热门文章

  1. C#_细说Cookie_Json Helper_Cookies封装
  2. JavaScript基础---语言基础(1)
  3. 怎样才算全面的分类?
  4. Monte Carlo概率模型进行分子动力学模拟并计算苯甲醚键值
  5. MIT_18.03_微分方程_Fourier_Series_傅里叶级数_Notes
  6. java从property中取值,JAVA读取PROPERTIES配置文件
  7. 服务器登陆密码到期登不上去_英雄联盟手游注册系统炸服怎么回事?服务器瘫痪登不上解决方法[多图]...
  8. 【Paper】2022_多无人机系统的分布式最优编队控制
  9. 3.3 神经网络的输出-深度学习-Stanford吴恩达教授
  10. 8.7 程序示例--异常检测-机器学习笔记-斯坦福吴恩达教授