算法核心:
每小时对应一个费率,统计在一段时间内的费用;
拆成秒的模式,在每一个时间段逐项相加;(由于这道题和小时相关,所以不拆成秒数相加的形式可能更好做)
个人觉得当时的做法挺麻烦的,以后有时间了再优化吧
AC CODE:
#include <iostream>
#include <algorithm>
#include <utility>
#include <vector>
#include <map>
using namespace std;
const int maxn = 1010;
int rate[24];
struct REC{
string name;
int time,statu,month;
}rec[maxn];
struct PER_REC{
pair<int,int> time_rec;
int minute,cost,month;
PER_REC(){
cost = 0;
}
};
map<string,vector<PER_REC> > mp;
bool cmp(REC a,REC b){
if(a.name!=b.name) return a.name < b.name;
else return a.time<b.time;
}
int n,month,sum_rate = 0;
int main() {
int sum=0;
for(int i=0;i<24;i++){
scanf("%d",&rate[i]);
sum+=rate[i];//sum是一整天的费率
sum_rate += rate[i]*60;
}
cin >> n;
for(int i=0;i<n;i++){
string statu;
int m,d,h,mi;
cin >> rec[i].name;
scanf("%d:%d:%d:%d",&m,&d,&h,&mi);
month = m;
cin >> statu;
rec[i].statu = statu=="on-line"?1:0;
rec[i].time = d*24*60+h*60+mi;
rec[i].month = month;
}
sort(rec,rec+n,cmp);
for(int i=0;i<n-1;i++){
if(rec[i].name!=rec[i+1].name || !(rec[i].statu==1 && rec[i+1].statu==0)) continue;//名字不一样或者状态不对就跳过
PER_REC tmp;
tmp.time_rec = {rec[i].time,rec[i+1].time};
tmp.minute = rec[i+1].time - rec[i].time;//统计这一对记录有多少分钟
tmp.month = rec[i].month;//因为题目局限在一个月内
int a = rec[i].time,b = rec[i+1].time;
while(a<b){//***这一段是对费用进行累加的核心
int index = a%1440/60;//代表通话的起始时间的费率下标
int up = a/1440*1440+(index+1)*60>b?b:a/1440*1440+(index+1)*60;//到下一个时间点的分钟数
int sum = rate[index] * (up-a);//两段之间的分钟数总和
tmp.cost += rate[index] * (up-a);//计算这一个时间段有多少费用
a = up;//更新起始时间到新的一段去
}
mp[rec[i].name].push_back(tmp);
}
for(auto it:mp){
double sum = 0;
printf("%s",it.first.c_str());
vector<PER_REC> tmp = it.second;
printf(" %02d\n",tmp[0].month);
for(auto it1:tmp){
int time1 = it1.time_rec.first,time2 = it1.time_rec.second;
printf("%02d:%02d:%02d",time1/60/24,time1%(24*60)/60,time1%(24*60)%60);
printf(" %02d:%02d:%02d",time2/60/24,time2%(24*60)/60,time2%(24*60)%60);
printf(" %d $%.2f\n",it1.minute,it1.cost*1.0/100);
sum += it1.cost*1.0/100;
}
printf("Total amount: $%.2f\n",sum);
}
return 0;
}