1016 Phone Bills (25 分)

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-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:
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
这里参考https://blog.csdn.net/qq_22194315/article/details/54582970#commentBox这篇
题目意思请自行翻译
这里主要分为三块,一个排序、一个计算花费、一个主函数
对于每个顾客的通话信息使用结构体存储,这里名字的长度最小为21(不要问为什么,死在这里很久)

struct node{
	char name[21];
	int month;
	int day;
	int hour;
	int min;
	int is_on;
} test[1010];

对输入的信息进行排序,按照姓名name、月month、日day、时hour、分min从小到大排序,这里最后一个对是结束还是开始通话排序对结果没影响,毕竟按时间排序了,通话时间小肯定排在前面。

int cmp(node t1,node t2){
	if(strcmp(t1.name,t2.name)!=0) return strcmp(t1.name,t2.name)<0;
	else if(t1.month!=t2.month) return t1.month<t2.month;
	else if(t1.day!=t2.day) return t1.day<t2.day;
	else if(t1.hour!=t2.hour) return t1.hour<t2.hour;
	else if(t1.min!=t2.min) return t1.min<t2.min;
	else return t1.is_on>t2.is_on;
}

计算花费,形参中on表示打电话,off表示挂电话,time使用引用,表示本次通话花费的时间,money使用引用,表示本次通话所花的钱,使用引用是因为一个函数只能返回一个变量,为满足输出每次的时长和花费。
根据题目,能够确定on中month、day、hour、min其中肯定有比off的小,所以从min不断增加,并在其中判断if(temp.min>=60)是否加一小时或加一天if(temp.hour>=24)
注:题目中说明保证测试案例为一个月中的数据,所以可以不必判断month的大小。

void get_ans(int on,int off,int &time,int &money){
	node temp=test[on];
	while(temp.month<test[off].month||temp.day<test[off].day||temp.hour<test[off].hour||temp.min<test[off].min){
		temp.min++;
		time++;
		money+=spend[temp.hour];
		if(temp.min>=60){
			temp.min=0;
			temp.hour+=1;
		}
		if(temp.hour>=24){
			temp.hour=0;
			temp.day+=1;
		}
	}
} 

主函数:这里的输入使用了scanf格式化输入(这里笔记本记好,感觉很有用),避免了提取时间中的month、day、hour、min这些使用int存储的数据。接下来就是排序,在排序后相同名字的信息会在一起,此时需要对相同姓名的信息进行遍历,对每一对(on在上,off邻接着在下),这里使用mark标记,具体请看代码,在保证有一对on,off的情况下,输出姓名和月份,每找到一对就传入get_ans函数并输出日、时、分,以及时间和钱。再找到所有on,off对后输出总金额。
注:本题总花费为0时,什么信息都不输出。观察输出,金额要除以100,由于输出为小数点两位,使用printf格式化输出。

#include <iostream>
#include <stdio.h>
#include <algorithm> 
#include <string.h>
using namespace std;
int spend[25];
struct node{
	char name[21];
	int month;
	int day;
	int hour;
	int min;
	int is_on;
} test[1010];
int cmp(node t1,node t2){
	if(strcmp(t1.name,t2.name)!=0) return strcmp(t1.name,t2.name)<0;
	else if(t1.month!=t2.month) return t1.month<t2.month;
	else if(t1.day!=t2.day) return t1.day<t2.day;
	else if(t1.hour!=t2.hour) return t1.hour<t2.hour;
	else if(t1.min!=t2.min) return t1.min<t2.min;
	else return t1.is_on>t2.is_on;
}
void get_ans(int on,int off,int &time,int &money){
	node temp=test[on];
	while(temp.month<test[off].month||temp.day<test[off].day||temp.hour<test[off].hour||temp.min<test[off].min){
		temp.min++;
		time++;
		money+=spend[temp.hour];
		if(temp.min>=60){
			temp.min=0;
			temp.hour+=1;
		}
		if(temp.hour>=24){
			temp.hour=0;
			temp.day+=1;
		}
	}
} 
int main(){
	for(int i=0;i<24;i++){
		scanf("%d",&spend[i]);
	}
	int n;
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		scanf("%s",&test[i].name);
		scanf("%d:%d:%d:%d",&test[i].month,&test[i].day,&test[i].hour,&test[i].min);
		char temp[10];
		scanf("%s",&temp);
		if(strcmp(temp,"on-line")==0) test[i].is_on=1;
		else test[i].is_on=0;
	}
	sort(test,test+n,cmp);
	int i,j,mark,sum,k;
	for(i=0;i<n;i++){
		sum=0;//总花费
		mark=0;
		for(j=i;j<n;j++){//找到相同姓名的范围
			if(strcmp(test[i].name,test[j].name)!=0) break;
			if(test[j].is_on==1&&mark==0) mark=1;
			if(test[j].is_on==0&&mark==1) mark=2;//这两句保证on在上,off在下
		}
//		cout<<i<<" "<<j<<endl;//
		if(mark==2){
			k=i;
			printf("%s %02d\n",test[k].name,test[k].month);
			for(k=i;k+1<j;k++){
				if(test[k].is_on==1&&test[k+1].is_on==0){//找到一对相连的on,off
					printf("%02d:%02d:%02d %02d:%02d:%02d ",test[k].day,test[k].hour,test[k].min,test[k+1].day,test[k+1].hour,test[k+1].min);
					int time=0,money=0;
					get_ans(k,k+1,time,money);
					sum+=money;//累加
					printf("%d $%.2f\n",time,money/100.0);
					k+=1;
				}		
			}
			printf("Total amount: $%.2f\n",sum/100.0);
		}		
		i=j-1;		
	}
//	cout<<endl;
//	for(int i=0;i<n;i++){
//		printf("%s ",test[i].name);
//		printf("%02d:%02d:%02d:%02d %d\n",test[i].month,test[i].day,test[i].hour,test[i].min,test[i].is_on);
//	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值