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 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-linerecords 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:

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:

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

这道题做了蛮久。一开始没有明白给出的20个数字是怎么对应时间收费的,后来在如何给一个人的打电话和挂电话记录的匹配上碰到了困难,最后在测试点3上也卡了一下。

好在博客上大佬很多,都很耐心地给出了详细的题解,看看他们的思路和代码最终AC了这道题。

题目大意:

一个长途电话公司向其顾客的收费规则如下:

每分钟长途电话收费的价格取决于打电话的时间,拨通电话时开始计时,直到挂断电话。每个月公司会向顾客发送账单,而你的工作就是列好每月的账单。

输入的数据格式:

输入的数据包含收费结构以及通话记录。

首先给出收费结构。收费结构由24个非负整数组成,代表了从00:00到01:00、01:00到02:00......时间段内的收费价格(美分/每分钟),譬如收费结构的第一个数字是10,则代表在00:00到01:00这个时间段内通话的话,每分钟需要交10美分。

之后给出一个整数N,代表通话记录数量。紧跟着就是N条通话记录,每条记录包含了通话人姓名、通话时间(月:日:时:分,如01:01:06:01代表1月1日6点1分)以及通话类型(即拨打电话还是挂断电话)。

范围说明:每个测试用例的日期都在一个月内。每个on-line的通话记录都必须匹配同一个顾客的off-line,如果有落单的on-line或者off-line,那么直接忽略,后期不输出。题目保证至少有一个通话的on-line和off-line是匹配的,你可以假设一个顾客不会在同一个时间有两条通话记录。

输出的数据格式:

按照顾客的首字母大小写从小到大输出每个顾客的账单(当然,没有一条on-line和off-line匹配的通话记录的顾客不输出,其没有消费)。每个顾客的账单需要包括:第一行——顾客名、通话月份;第二行至第n行——通话开始时间、通话结束时间、通话时长、本次通话的价格(美元);最后一行——总通话价格(美元)。

解题思路:

  • 用大小为24的数组和vector分别存储收费策略以及通话记录,建立结构体Record表示一条通话记录;
  • 对输入并保存在vector中的通话记录进行排序,首先按照顾客姓名从小到大排序,接着按照通话时间的先后顺序进行排序(详见compare函数);
  • 循环遍历vector数组,比较前一个记录和后一个记录是否匹配,然后按照匹配结果输出账单

我碰到的问题及解决方法:

  1. ​​​​​​​怎么判断通话记录是否有效:vector中存储的记录按照时间先后已经排了一遍序,那么就保证了当有多个on-line接连出现时,新的on-line覆盖旧的on-line(即旧的的on-line无效)。只需要判断当前的顾客名与前一条记录顾客名相同,且当前为off-line、前一条为on-line记录即可确认为一对有效的通话记录;
  2. 怎么计算收费:这里我采用了略微麻烦一些但是好理解的计算方法。第一种类型是同月不同天,第二种类型是同月同天不同小时,第三种类型是同月同天同小时(测试点3,在这里踩了坑),详见代码,很好理解。

代码如下:

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

int rate[25] = {0};

struct Record{
	string name;
	string state;  //1为on-line,0为off-line
	int month,day,hour,minute; 
};

bool compare(Record a,Record b){
	if(a.name != b.name)
		return a.name < b.name;
	else if(a.month != b.month)
		return a.month < b.month;
	else if(a.day != b.day)
		return a.day < b.day;
	else if(a.hour != b.hour)
		return a.hour < b.hour;
	else 
		return a.minute < b.minute;
}

double countMoney(Record a,Record b){
	int sum = 0;
	if(b.day - a.day != 0)
	{
		sum += (b.day - a.day-1) * rate[24] * 60; 
		int ttt = 0;
		for(int i = a.hour +1 ; i <= 23 ; i ++)
		{
			ttt += rate[i];
			sum += rate[i]*60;
		}	
		for(int i = 0 ; i <= b.hour-1;i++)
			sum += rate[i]*60;
		sum += ((60-a.minute)*rate[a.hour]);
		sum += (b.minute*rate[b.hour]);
	}	
	else{
		for(int i = a.hour+1 ; i <= b.hour-1; i ++){
			sum += rate[i]*60;
		}
		if(a.hour == b.hour) //在同一天同一个小时(测试点3)
		{
			sum += (b.minute-a.minute)*rate[a.hour];
		} 
		else{
			sum += ((60-a.minute)*rate[a.hour]);
			sum += (b.minute*rate[b.hour]);
		}
	}
	return (sum*1.0)/100.0;
}


int main(){
	for(int i = 0 ; i < 24 ; i ++)
	{
		scanf("%d",&rate[i]);
		rate[24] += rate[i];   //打一天电话一分钟所要花费的总价
	}
	int n;
	scanf("%d",&n);
	vector<Record> records;
	for(int i = 1 ; i <= n ; i ++)
	{
		Record record;
		cin>>record.name;
		scanf("%d:%d:%d:%d",&record.month,&record.day,&record.hour,&record.minute);
		cin>>record.state;
		records.push_back(record);
	}
	sort(records.begin(),records.end(),compare);
	Record tag;
	tag.name = "";
	records.push_back(tag);
	double money = 0.0;
	bool flag = false;
	for(int i = 1 ; i < records.size(); i ++){
		if(records[i].name == records[i-1].name && (records[i].state=="off-line" && records[i-1].state == "on-line")){
			if(flag == false){
				flag = true;
				cout<<records[i].name<<" ";
				printf("%02d\n",records[i].month);
			}
			double temp_money = countMoney(records[i-1],records[i]);
			int time = (records[i].day*24*60 + records[i].hour*60 + records[i].minute)-(records[i-1].day*24*60 + records[i-1].hour*60 + records[i-1].minute);
			printf("%02d:%02d:%02d %02d:%02d:%02d %d $%.2f\n",records[i-1].day,records[i-1].hour,records[i-1].minute,records[i].day,records[i].hour,records[i].minute,time,temp_money); 
			money += temp_money;
		}
		else if(records[i].name != records[i-1].name && money > 0.001){
			printf("Total amount: $%.2f\n",money);
			money = 0.0;
			flag = false;
		}
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值