PAT甲级-1016-Phone Bills(排序+map)

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.

Input Specification:

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.

Output Specification:

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.

Sample Input 1:
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
Sample Output 1:
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
题目关键信息:

①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.

  • 前后两个call来自同一个顾客,并且前一个call是online(接通)状态,而后一个call是offline(挂断)状态,这个call才算是生效。

②Bills must be printed in alphabetical order of customers’ names.
The calls must be listed in chronological order.

  • 账单要按照顾客姓名的字典顺序排序,通话记录要按照时间顺序排序。

  • 分析:其实②正好为①做铺垫,按顾客姓名的字典顺序以及时间顺序进行排序后,从头至尾便很容易找到同一个顾客,也很容易找到该顾客的前后两次通记录

数据结构选择:

采用map存储 每一个顾客(key)所对应的通话信息集合(value),采用vector存储通话信息集合(因为数组长度大小未知,因此采用变长的vector存),十分注意:vector中每两个相邻的元素即为一通电话!

  • 非常容易错的一点,由于配对,因此不是i++,而是i+=2!!!!
for(int i = 1; i < temp.size(); i+=2){
}
  • 非常容易错的一点,ans[info[i-1].name].push_back(info[i-1]);ans[info[i].name].push_back(info[i]);的顺序不要颠倒!!!!
for(int i = 1; i < n; i++){//筛选有效通话 
		if(info[i].name==info[i-1].name && info[i].status==0 && info[i-1].status==1){
			ans[info[i-1].name].push_back(info[i-1]);
			ans[info[i].name].push_back(info[i]);
		}
	}
求话费函数:

注:rate[24]用于计算跨天电话的话费。
在这里插入图片描述

写错了:应该是除以100.。。。
  • 改进,在程序中实现:不用管中间过程,取两个端点一算一减即可。这样代码还可重用!

在这里插入图片描述

代码如下

#include<iostream>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
struct node{
	string name;
	int month,day,hour,minute,time,status;
}info[1005];
int rate[25] = {0};
map<string,vector<node>> ans;
bool cmp(node a,node b){
	if(a.name!= b.name) return a.name<b.name;
	return a.time<b.time;
}
double fare(node a){
	double res = a.minute*rate[a.hour]+a.day*rate[24]*60;
	for(int i = 0; i < a.hour; i++){
		res += rate[i]*60;
	}
	return res / 100;
}
int main()
{
	int n;string s;
	for(int i = 0; i < 24; i++){
		scanf("%d", &rate[i]);
		rate[24] += rate[i];
	} 
	cin>>n;
	for(int i = 0; i < n; i++){
		cin>>info[i].name;
		scanf("%d:%d:%d:%d", &info[i].month,&info[i].day,&info[i].hour,&info[i].minute);
		cin>>s;
		info[i].status = (s=="on-line")?1:0;
		info[i].time = info[i].day*24*60+info[i].hour*60+info[i].minute;
	}
	sort(info, info+n, cmp);//排序 
	for(int i = 1; i < n; i++){//筛选有效通话 
		if(info[i].name==info[i-1].name && info[i].status==0 && info[i-1].status==1){
			ans[info[i-1].name].push_back(info[i-1]);
			ans[info[i].name].push_back(info[i]);
		}
	}
	map<string, vector<node>>:: iterator it;
	for(it = ans.begin(); it != ans.end(); it++){
		double ans,total = 0.0;
		vector<node> temp = it->second;
		cout<<it->first<<" ";
		printf("%02d\n", temp[0].month);
		for(int i = 1; i < temp.size(); i+=2){
			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,fare(temp[i])-fare(temp[i-1]));
			total += fare(temp[i])-fare(temp[i-1]);
		}	
		printf("Total amount: $%.2f\n", total);
	}
	return 0;
}
发布了110 篇原创文章 · 获赞 746 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_42437577/article/details/104123607