1016 Phone Bills
目录
概述:
一些小的注意点
AC代码
概述:
这道题是我迄今做出来的最复杂的一道PAT了,该题被归类到排序专题下,其实还涉及到大量的字符串处理等别的我暂时也说不出的知识点。
排序函数我写了两个,1是cmp,用于让记录按照时间从早到晚的顺序排列,2是cmp2,让用户按照姓名的字母顺序从小到大排列,可以说是很简单的两个函数。
结构体写了三个,分别是record,user,call。其中user包含call数组。record用于读入记录,属性对应输入。call是每一对记录(on-line和off-line),包括开始结束时间,分钟数,话费。user是每个用户,call_num代表记录的条数,用于最后的输出使用。
struct call{char startTimeExMonth[15];char endTimeExMonth[15];int call_minute = 0;double call_money = 0;
};struct user{char name[22] = "";char month[3] = ""; call calls[maxn];int call_num = 0;double total_money = 0;
}users[maxn];struct record{char name[22] = "";char time[15] = "";char state[10] = "";
}recs[maxn][maxn];
除了比较函数外还写了两个函数,getMinute输入开始和结束时间,输出总共的分钟数。getMoney输入开始、结束时间和单位话费数组,输出美元数(1美元=100美分)。
这两个函数一开始都有让我共同纠结的点,比如遇到大单位数字小,小单位数字大两个数如何相减。其实可以放心使用 x - y = (x-0)-(y-0)
int getMinute(char startTime[15],char endTime[15]){int startMonth = 0;int startDay = 0;int startHour = 0;int startMin = 0;int endMonth = 0;int endDay = 0;int endHour = 0;int endMin = 0;sscanf(startTime,"%d:%d:%d:%d",&startMonth,&startDay,&startHour,&startMin);sscanf(endTime,"%d:%d:%d:%d",&endMonth,&endDay,&endHour,&endMin);//01:02:00:01 01:04:23:59 4318return (endDay*24*60+endHour*60+endMin) - (startDay*24*60+startHour*60+startMin);
}double getMoney(char startTime[15],char endTime[15],int tolls[24]){int startMonth = 0;int startDay = 0;int startHour = 0;int startMin = 0;int endMonth = 0;int endDay = 0;int endHour = 0;int endMin = 0;sscanf(startTime,"%d:%d:%d:%d",&startMonth,&startDay,&startHour,&startMin);sscanf(endTime,"%d:%d:%d:%d",&endMonth,&endDay,&endHour,&endMin);int fullday_money = 0;//一整天的话费 for(int i=0;i<24;i++){fullday_money += 60*tolls[i];}int start_minute_money = 0;//假设从0点开始打,打到整分的话费for(int i=0;i<startHour;i++){start_minute_money += 60*tolls[i];}int end_minute_money = 0;for(int i=0;i<endHour;i++){end_minute_money += 60*tolls[i];}int startMoney = startDay*fullday_money+start_minute_money+tolls[startHour]*startMin;int endMoney = endDay*fullday_money+end_minute_money+tolls[endHour]*endMin;return (endMoney-startMoney)/100.0;
}
一些小的注意点
1. 怎样比较时间先后:由于时间是以
01:01:06:01
月:日:时:分的形式从大到小排列的字符串,所以在cmp中写strcmp即可。
2. 怎样得到一对时间,对于每一个人按照时间排好顺序的记录,判断本条是否状态为在线且下条状态为离线,注意,由于相等时strcmp返回的是0,要记得加取反符号
if(!strcmp(recs[i][j].state,"on-line")&&!strcmp(recs[i][j+1].state,"off-line"))
3. 那么多条记录,怎样将某个人的记录归类,这是我第一次做。开辟一个二维结构体数组,第一维表示每个人,通过strcmp对比当前读入的人名和每一维第一个元素的人名,如果有则为那一行的列数加一,如果没有就增加行数。
for(int i=0;i<n;i++){bool hasFound = false;scanf("%s %s %s",name,time,state);//通过字符串比对姓名,看能否找到他for(int j=0;j<row;j++){if(strcmp(recs[j][0].name,name)==0){strcpy(recs[j][cols[j]].name,name);strcpy(recs[j][cols[j]].time,time);strcpy(recs[j][cols[j]].state,state);cols[j]++;hasFound = true;break;}}if(!hasFound){//没找到他,新开一列 strcpy(recs[row][0].name,name);strcpy(recs[row][0].time,time);strcpy(recs[row][0].state,state);cols[row]++;row++;} }
4. 一开始我的2,3测试点是错误的,看了别的博客才知道,没有进行合法性校验,在读题时把每个测试用例至少有一对记录合法理解成每个人至少有一对记录合法。正确方式是如果某人没有记录,应当不予以输出,即加入如下代码:
const double eps = 1e-3;
if(abs(users[i].total_money-0)<eps)continue;
AC代码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<bits/stdc++.h>
using namespace std;const int maxn = 1010;
const double eps = 1e-3;struct call{char startTimeExMonth[15];char endTimeExMonth[15];int call_minute = 0;double call_money = 0;
};struct user{char name[22] = "";char month[3] = ""; call calls[maxn];int call_num = 0;double total_money = 0;
}users[maxn];struct record{char name[22] = "";char time[15] = "";char state[10] = "";
}recs[maxn][maxn];bool cmp(record a,record b){return strcmp(a.time,b.time)<0;
}bool cmp2(user a,user b){return strcmp(a.name,b.name)<0;
}int getMinute(char startTime[15],char endTime[15]){int startMonth = 0;int startDay = 0;int startHour = 0;int startMin = 0;int endMonth = 0;int endDay = 0;int endHour = 0;int endMin = 0;sscanf(startTime,"%d:%d:%d:%d",&startMonth,&startDay,&startHour,&startMin);sscanf(endTime,"%d:%d:%d:%d",&endMonth,&endDay,&endHour,&endMin);//01:02:00:01 01:04:23:59 4318return (endDay*24*60+endHour*60+endMin) - (startDay*24*60+startHour*60+startMin);
}double getMoney(char startTime[15],char endTime[15],int tolls[24]){int startMonth = 0;int startDay = 0;int startHour = 0;int startMin = 0;int endMonth = 0;int endDay = 0;int endHour = 0;int endMin = 0;sscanf(startTime,"%d:%d:%d:%d",&startMonth,&startDay,&startHour,&startMin);sscanf(endTime,"%d:%d:%d:%d",&endMonth,&endDay,&endHour,&endMin);int fullday_money = 0;//一整天的话费 for(int i=0;i<24;i++){fullday_money += 60*tolls[i];}int start_minute_money = 0;//假设从0点开始打,打到整分的话费for(int i=0;i<startHour;i++){start_minute_money += 60*tolls[i];}int end_minute_money = 0;for(int i=0;i<endHour;i++){end_minute_money += 60*tolls[i];}int startMoney = startDay*fullday_money+start_minute_money+tolls[startHour]*startMin;int endMoney = endDay*fullday_money+end_minute_money+tolls[endHour]*endMin;return (endMoney-startMoney)/100.0;
}int main(){int row = 0;//行,二维结构体数组的第一维下标,代表某个用户int cols[maxn] = {0};//记录每一行的列数 //读入每个时段的电话费int tolls[24];for(int i=0;i<24;i++){scanf("%d",&tolls[i]);}//读入记录的数量int n;scanf("%d",&n);//开始读入记录,同一个用户数组下标的第一维得是一样的char name[22] = "";char time[15] = "";char state[10] = "";for(int i=0;i<n;i++){bool hasFound = false;scanf("%s %s %s",name,time,state);//通过字符串比对姓名,看能否找到他for(int j=0;j<row;j++){if(strcmp(recs[j][0].name,name)==0){strcpy(recs[j][cols[j]].name,name);strcpy(recs[j][cols[j]].time,time);strcpy(recs[j][cols[j]].state,state);cols[j]++;hasFound = true;break;}}if(!hasFound){//没找到他,新开一列 strcpy(recs[row][0].name,name);strcpy(recs[row][0].time,time);strcpy(recs[row][0].state,state);cols[row]++;row++;} }//对所有列进行排序for(int i=0;i<row;i++){sort(recs[i],recs[i]+cols[i],cmp);}for(int i=0;i<row;i++){//对于每一个人
// printf("%s %c%c\n",recs[i][0].name,recs[i][0].time[0],recs[i][0].time[1]); //赋予姓名 strcpy(users[i].name,recs[i][0].name);for(int j=0;j<2;j++){users[i].month[j]=recs[i][0].time[j];}double total_money = 0;double call_money = 0;int call_minute = 0;int call_num = 0;char startTime[15] = "";char endTime[15] = "";for(int j=0;j<cols[i]-1;j++){if(!strcmp(recs[i][j].state,"on-line")&&!strcmp(recs[i][j+1].state,"off-line")){strcpy(startTime,recs[i][j].time);strcpy(endTime,recs[i][j+1].time);char startTimeExMonth[15] = "";for(int i=0;i<8;i++){startTimeExMonth[i] = startTime[3+i];}char endTimeExMonth[15] = "";for(int i=0;i<8;i++){endTimeExMonth[i] = endTime[3+i];}users[i].calls[call_num].call_minute = getMinute(startTime,endTime);users[i].calls[call_num].call_money = getMoney(startTime,endTime,tolls);total_money += getMoney(startTime,endTime,tolls);strcpy(users[i].calls[call_num].startTimeExMonth,startTimeExMonth);strcpy(users[i].calls[call_num].endTimeExMonth,endTimeExMonth);call_num++;}}users[i].call_num = call_num;users[i].total_money = total_money;}//对用户按照总的话费进行排序 sort(users,users+row,cmp2);//输出for(int i=0;i<row;i++){if(abs(users[i].total_money-0)<eps)continue;printf("%s %s\n",users[i].name,users[i].month);for(int j=0;j<users[i].call_num;j++){printf("%s %s %d $%.2f\n",users[i].calls[j].startTimeExMonth,users[i].calls[j].endTimeExMonth,users[i].calls[j].call_minute,users[i].calls[j].call_money);}printf("Total amount: $%.2f\n",users[i].total_money);} return 0;
}
相关文章:
C# GDI+ 简单绘图 (三) 仿浏览器截屏效果
感谢大家的支持,这几天从早忙到晚,一个字累呀!!!现在挺困的,但是又不习惯这么早睡觉,哎~~还是利用这个时间继续来写第三篇吧. 前两篇已经基本向大家介绍了绘图的基本知识.那么,我就用我们上两篇所学的,做几个例子. 我们先来做一个简单的----仿QQ截图,关于这个…

POJ 1236 Network of Schools(tarjan)
Network of SchoolsDescription A number of schools are connected to a computer network. Agreements have been developed among those schools: each school maintains a list of schools to which it distributes software (the “receiving schools”). Note that if B …

如何设置网页自动刷新(JSP,JS,HTML)
http://blog.163.com/ylx282006126/blog/static/59772717201111685917664/ 转载于:https://www.cnblogs.com/liuzhuqing/p/7480284.html

1084 Broken Keyboard
两个注意的点 1.本题被归到散列专题下,但是由于是逐字符地映射到整形,可以直接把布尔型哈希数组的大小设置为ASCII的数量128,然后直接将字符作为数组下标(如果是字符串,才需要自己写一个哈希函数,将字符串映射到整形&…

Android提示框与通知的使用
1.通知 Android 3.0以前使用的方法 1 NotificationManager nm (NotificationManager) getSystemService(NOTIFICATION_SERVICE); 2 Notification notification new Notification(R.drawable.dss, 3 "通知到了", Syste…

nginx安全日志分析脚本的编写
https://blog.csdn.net/nextdoor6/article/details/51914966

[转]笑死人的考试填空
高考完后又是中考,考题千奇百怪,答卷也五花八门。真佩服现在的学生啊,思维跳脱,天马行空,和我们那时候的循规蹈矩,差别太大了,呵呵。看一组语文试卷中的填空题:1.__________…

1033 旧键盘打字
1. 非常奇怪,明明都说了用下划线替代空格,但是用scanf读入的时候就会有1个测试点没通过,换成cin.getline就通过了 2.3种情况下对应的哈希表赋值为true。1是上来就赋值,2是对于大写字母把对应小写字母也赋值,这里注意直…

OLE 操作Excel 详解(转)
使用Excel模板进行报表的开发. 今年搞的Excel比较多,总结了一下,相信常用的操作包含的差不多了。 可以首先定义一个无内容的Excel报表模板文件. 通过Tcode SMW0 上传至SAP数据库中备用.(注: Web对象应该选择’WebRFC 应用程序的二进制数据’) 开发程序…

只需3分钟,就能轻松创建 一个SpreadJS的React项目
概述SpreadJS 纯前端表格控件 V11.2(SP2) 已经全面支持了 React 的拓展。接下来我们看下如何利用3分钟快速创建一个 SpreadJS 的 React 项目。1.新建React 项目(耗时 1 Min)直接运行:npx create-react-app react-spread-sheets还不清楚什么是…

1039 到底买不买
很典型的散列题,对于shop和eva有的珠子(即字符),各开一个128长度的整形散列表计数,将字符作为下标读入。 然后从0~127进行遍历,看每个下标下两个散列表的数量,如果有shop<eva说明不买,但是遍历仍然要继…

什么是Linq
最近一直利用业余的时间来研究Linq,估计这样的文章在对于园子里很多牛人来说就有点小儿科了,前段时间写了一个Linq To Sql体验的小例子,感觉很简洁程序上操作体验不错,我写这些的文章目的是自我学习笔记的备用和查看,当…

OSS正式支持IPv6公测
背景 6月20日阿里云宣布全面支持IPv6, 随后阿里云开放对象存储OSS也逐步开始向用户公测。 公测步骤 正常使用IPv6服务,除了OSS端支持还需要客户端支持,我们做一些检查证明客户端具备访问 IPv6的能力,再使用OSS SDK或工具通过IPv6 …

C++中定义类的对象:用new和不用new的区别
Point p1; Point *p2new Point(); p1 由系统创建并释放,不用担心会出现内存泄露,但是生命期只有在本区域的大括号内,出了大括号就没用了。 P2 是指针,要自己释放,用不好很危险,用好了功能强大,…

1043 输出PATest
开一个长度为6的整型数组分别记录6个字符的数量,输出的时候条件是数组中至少存在一个不为零的元素 while(PATest[0]||PATest[1]||PATest[2]||PATest[3]||PATest[4]||PATest[5]){//当6个还有一个不为0 AC代码 #include<cstdio> #include<cmath> #inc…

[转载 js] YUI解决mouseout事件冒泡的办法
原文出处:http://design.alibaba-inc.com/?qnode/727================&am…

adodb.RecordSet的属性和方法
为了更精确地跟踪数据,要用RecordSet组件创建包括数据的游标,游标就是储存在内存中的数据: rs Server.CreateObject("ADODB.RecordSet") rs.Open(sqlStr,conn,1,A) 注:A1表示读取数据;A3表示新增、改动或删…

给女友讲讲设计模式——适配器模式(JAVA实例)5
前言 有这样一个人,看到别人一个个开餐馆赚了好多钱,于是自己也很想在餐饮业这方面大展拳脚,他从别人那里学到了他们的理念,还学习到了他们真正开店的经验。不但如此,他还引进了除了吃饭意外其他的服务,例如…

1041 Be Unique
1.依旧是散列题,开一个整形的哈希数组bets[10010]来计数,最后数目为1的,也就是unique 2.注意,可能为1的不止一个,要输出第一个输入的unique,那么需要记录下读入的顺序,可以开辟一个数组inputs[…

SWT图像处理入门
SWT图像处理入门 Standard Widget Toolkit ( SWT ,标准窗口小部件工具箱),是在 Eclipse 平台上使用的窗口小部件工具箱,它能向开发者提供和本机平台一致的用户界面和比较稳定的性能,也提供了强大的图像处理功能。本文首先介绍 SWT…

MyEclipse中的快捷键
MyEclipse 快捷键1(CTRL)-------------------------------------Ctrl1 快速修复CtrlD: 删除当前行 CtrlQ 定位到最后编辑的地方 CtrlL 定位在某行 CtrlO 快速显示 OutLine CtrlT 快速显示当前类的继承结构 CtrlW 关闭当前Editer CtrlK 快速定位到下一个 CtrlE 快速显示当…

CocoaPods原理(一)
CocoaPods介绍 CocoaPods 是开发 OS X 和 iOS 应用程序的一个第三方库的依赖管理工具。利用 CocoaPods,可以定义自己的依赖关系 (称作 pods),并且随着时间的变化,以及在整个开发环境中对第三方库的版本管理非常方便。 CocoaPods 背后的理念主…

1055 The World‘s Richest
开始的做法是,对于每一个case,都在整个person数组内进行遍历,把所有年龄符合要求的都放进一个临时数组,然后对临时数组进行排序,再根据要求的数目输出。但是这么做会有一个测试用例因为超时而通不过。 穷则思变。于是…

IOS时间传递机制简记
事件传递顺序:自定义View -- > UIview --> RootViewController --> UIWindow -->UIApplication -->Appdelegate -->nil 注: //分发事件,将当前的触摸事件分发给当前对象的下一个响应者 //如果当前对象处理了当前事件&am…

HDOJ2270(How Many Friends Will Be Together With You)
#include <iostream>using namespacestd;const int MAX 1000005;intfr[MAX];intmain(){ int n, i, tt, sum; while(cin>>n) { for(i 1; i < n; i) fr[i] i;//初始化,一开始每个都是独立的,并无朋友 …

在linux环境下重启oracle数据库,解决密码过期的问题
(1) 以oracle身份登录数据库,命令:su – oracle (2) 进入Sqlplus控制台,命令:sqlplus /nolog (3) 以系统管理员登录,命令:connect /as…

1075 PAT Judge
1. 这一题一开始,为了同一个人的数据更新得方便,我把id从字符串转化成整数,作为数组下标,但是注意了,每个学生还是要有字符串的id属性(根据下标得到),因为后面一旦排序,数组下标就毫无意义了。 …

MySQL 错误代码和消息
本章列出了当你用任何主机语言调用MySQL时可能出现的错误。首先列出了服务器错误消息。其次列出了客户端程序消息。 B.1. 服务器错误代码和消息 服务器错误信息来自下述源文件: 错误消息信息列在share/errmsg.txt文件中。“%d”和“%s”分别代表编号和字符…

一步步学习汇编(8)之指令
要理解ret,retf,call指令,必须要先理清以下汇编基础知识: 一. [bx]和内存单元<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />[bx]是什么呢? 和[0]有些类似…

【转】不分主副卡!全网通5.0时代到来
全网通在今天已经不是噱头了,它经历了有5年时间,从过去的全网通1.0到现在的全网通5.0,可以说有这长足的发展。今年,小米率先了支持全网通5.0的小米MIX 2S和红米Note5,可以双卡双待4G,一边打电话一边打游戏不…