这道题是模拟题。需要处理的就是花费的话费,我们假设一个月有31天,那N<1000,每人最少两条数据,最多500个人,则复杂度为500*31*1440(每天的分钟)*24(24种话费情况),而时间限制是200ms,会超时。所以我们考虑用前缀和的思想,sum[]表示即当前的时间距离每月的0点0分所花费的话费,则电话的结束时间所花费的sum[]-电话的开始时间所花费的sum[],即为该时间段的话费。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
using namespace std;
const int N=1010,M=31*1440+10;
int cost[24];
double sum[M];
struct record{//记录每条电话记录
int minutes;//距离每个月的0时0分的分钟数,便于利用前缀和计算话费
string state;//on-line还是off-line
string formative_time;//格式化时间便于输出 00:00:00
bool operator< (const record a){//重载运算符,使得结构体按时间从小到大排序
return minutes<a.minutes;
}
};
map<string,vector<record>> persons;//vector存储每个人的通话记录
int main(){
for(int i=0;i<24;i++) cin>>cost[i];
for(int i=1;i<M;i++) sum[i]=sum[i-1]+cost[(i-1)%1440/60]/100.0;//前缀数组初始化。i-1是因为6:59到7:00算的是6时的花费,所以要-1
int n;
cin>>n;
char name[25],state[20],formative_time[20];
int month,day,hour,minute;
for(int i=0;i<n;i++){
scanf("%s %d:%d:%d:%d %s",name,&month,&day,&hour,&minute,state);
sprintf(formative_time,"%02d:%02d:%02d",day,hour,minute);//sprintf函数打印到字符串中
int minutes=(day-1)*1440+hour*60+minute;
persons[name].push_back({minutes,state,formative_time});
}
for(auto person:persons){
auto name=person.first;//名字
auto records=person.second;//记录数
sort(records.begin(),records.end());//排序
double total=0;
for(int i=0;i+1<records.size();i++){
auto a=records[i],b=records[i+1];
if(a.state=="on-line"&&b.state=="off-line"){
if(!total)
printf("%s %02d\n",name.c_str(),month);//输出名字跟月份
cout<<a.formative_time<<" "<<b.formative_time;
cout<<" "<<b.minutes-a.minutes<<" ";
double c=sum[b.minutes]-sum[a.minutes];
printf("$%.2lf\n",c);
total+=c;
}
}
if(total)
printf("Total amount: $%.2lf\n", total);
}
return 0;
}