好久没敲代码 这段时间有空 又刷到这一题 结果wa了无数次
可能是有些生疏了吧
比较基础的一道模拟题 但细节是真的狠多…
基本思路
1.注意用scanf对数据进行读入
并用sprintf 将数据进行写入
2.前缀和的思维的思路
在存储每条记录的时间的时候存储从该月第一天第一个时刻的数值到当前时刻的分钟数
并预处理好从该月第一天第一个时刻到当前时刻的所有花费便可大大简化止之后的运算
当然还有很多需要注意的小点具体的会在代码注释中呈现
具体代码
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
struct Record
{
//注意这里的minute记录的应为从1号到当前时间的总和
//主要是为了之后的前缀和运算做准备
int minutes;
string state;
string format_time;
bool operator < (const Record&t) const{
return minutes<t.minutes;
}
};
map<string,vector<Record>>persons;
const int N=1010,M=31*1440+10;
int n;
int cost[24];
double sum[M];
int main(){
//每个时间段花费的钱
for(int i=0;i<24;i++){
cin>>cost[i];
}
//前缀和处理 时间所花费钱的总和
for(int i=1;i<M;i++){
//一天24h 即1440min
//cost[(i-1)]%1440 即表示这个时间段 每分钟所花费的金额
sum[i]=sum[i-1]+cost[(i-1)%1440/60]/100.0; //因为输入的金额单位为分 答案要求为元所以除100
}
//读入记录条数
cin>>n;
char name[30];
char state[30];
int month,day,hour,minute;
char format_time[30];
for(int i=0;i<n;i++){
scanf("%s %d:%d:%d:%d %s",name,&month,&day,&hour,&minute,state);
sprintf(format_time,"%02d:%02d:%02d",day,hour,minute);
//计算出从1号到当前时间的分钟总和
int minutes = day*1440+hour*60+minute;
persons[name].push_back({minutes,state,format_time});
}
for(auto &[name,record] : persons){
sort(record.begin(),record.end());
double total=0;
for(int i=0;i+1<record.size();i++){
auto a=record[i];
auto b=record[i+1];
if(a.state=="on-line"&&b.state=="off-line"){
//如果是第一次出现某人的记录的话
//则按照题目要求需要打印出姓名与账单月份
if(total==0){
printf("%s %02d\n",name.c_str(),month);
}
cout<<a.format_time<<' '<<b.format_time;
double c=sum[b.minutes]-sum[a.minutes];
printf(" %d $%.2lf\n",b.minutes-a.minutes,c);
total+=c;
}
}
if(total>0){
printf("Total amount: $%.2lf\n",total );
}
}
return 0;
}