题目描述
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 FORMAT
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.
翻译:每个测试文件包含一组测试数据。每组测试数据包括2部分:费用安排和通话记录。
费用安排由一行24个非负整数组成,分别为00:00 - 01:00的长途电话费,01:00 - 02:00的长途通话费,以此类推。
接下来一行包括一个正整数N (<= 1000),接着N行为通话记录。每个通话记录由用户名(20个字符不包含空格)、月份和日期 (mm:dd:hh:mm),和单词 “on-line” or “off-line”。
对于每组测试数据,所有的日期都在同一月内。每个“on-line”记录与按时间先后顺序排列的同一用户提供的“off-line”记录相配对。任何“on-line”记录如果未与“off-line”记录匹配则被忽略,”off-line”记录也是。数据保证输入中至少有一组通话记录可以匹配。你需要假设同一个用户不能在同一时间同时打两个电话。时间为24小时制。
OUTPUT FORMAT
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.
翻译:对于每组测试数据,你需要输出一份通话账单给每个客户。
账单必须按照客户姓名的字母序输出。对于每个客户,首先输出一行包括他的姓名和账单月份像样例中那样。接着对于每次通话记录,以 (dd:hh:mm)格式输出开始时间、结束时间,持续时间(分钟)和通话的花费。通话记录必须按照时间先后顺序排序。最后,像样例中展示的格式那样输出该月的总费用。
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
解题思路
这道题理解题意就挺麻烦的,是道大模拟题。首先需要将用户保存到一个map< string, int >,用于维护用户号。然后将string压到一个优先队列中,对string按字母序排序,再创建一个优先队列数组,用于保存通话记录。当然,这些数据结构都可以进行合并,根据个人喜好即可。注意:如果一个用户没有有效通话记录,则不输出!!很坑,怪我英文太差。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
#define INF 99999999
using namespace std;
struct Call{
int d,h,m,state;
Call(int day,int hour,int minute,int st):d(day),h(hour),m(minute),state(st){}
bool operator <(const Call &a)const{
return d==a.d?(h==a.h?m>a.m:h>a.h):d>a.d;
}
};
map<string,int> mp;
priority_queue<Call> q[1001];
priority_queue<string,vector<string>,greater<string> > qS;
int N,ccount=1,Mon[1010];//ccount用于记录客户号
double cost[24];
int Count(Call a,Call b){
int ad=a.d,ah=a.h,am=a.m;
int bd=b.d,bh=b.h,bm=b.m;
return ((bd-ad)*24+(bh-ah))*60+bm-am;
}
double Bill(Call a,Call b){
int ad=a.d,ah=a.h,am=a.m;
int bd=b.d,bh=b.h,bm=b.m;
ah=ah%24;bh=bh%34;
double sum=0.0;
while(ad<bd||ah<bh){
sum+=cost[ah]*(60-am);am=0;ah++;
if(ah==24)ah=0,ad++;
}
sum+=(bm-am)*cost[ah];
return sum/100;
}
int main(){
for(int i=0;i<24;i++)
scanf("%lf",&cost[i]);
scanf("%d",&N);
string s,state;
state.resize(10);
int mon,day,hour,min;
for(int i=0;i<N;i++){
cin>>s;
scanf("%d:%d:%d:%d %s",&mon,&day,&hour,&min,state.c_str());
if(!mp[s])mp[s]=ccount,qS.push(s),Mon[ccount++]=mon;
if(state[1]=='f')q[mp[s]].push(Call(day,hour,min,0));
else q[mp[s]].push(Call(day,hour,min,1));
}
while(!qS.empty()){
string tempS=qS.top();qS.pop();
Call pre(0,0,0,-1);
int Pre=0,flag=0;
double Sum=0;
while(!q[mp[tempS]].empty()){
Call tempC=q[mp[tempS]].top();q[mp[tempS]].pop();
if(tempC.state==1)pre=tempC,Pre=1;
if(tempC.state==0&&Pre){
double sum=Bill(pre,tempC);
if(!flag){
cout<<tempS;
printf(" %02d\n",Mon[mp[tempS]]);
flag=1;
}
Sum+=sum;
printf("%02d:%02d:%02d %02d:%02d:%02d %d $%.2lf\n",pre.d,pre.h,pre.m,tempC.d,tempC.h,tempC.m,Count(pre,tempC),sum);
Pre=0;
}
}
if(flag)printf("Total amount: $%.2lf\n",Sum);
}
return 0;
}